summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--Makefile.am20
-rw-r--r--NEWS43
-rw-r--r--README2
-rw-r--r--configure.ac35
-rw-r--r--m4/gssapi.m4114
-rw-r--r--m4/krb5-config.m4101
-rw-r--r--m4/krb5.m4206
-rw-r--r--m4/lib-depends.m49
-rw-r--r--m4/lib-pathname.m410
-rw-r--r--m4/remctl.m494
-rw-r--r--m4/snprintf.m49
-rw-r--r--m4/vamacros.m49
-rw-r--r--portable/asprintf.c12
-rw-r--r--portable/dummy.c12
-rw-r--r--portable/krb5-extra.c12
-rw-r--r--portable/krb5.h20
-rw-r--r--portable/macros.h35
-rw-r--r--portable/mkstemp.c14
-rw-r--r--portable/setenv.c19
-rw-r--r--portable/snprintf.c3
-rw-r--r--portable/stdbool.h20
-rw-r--r--portable/strlcat.c12
-rw-r--r--portable/strlcpy.c12
-rw-r--r--portable/system.h75
-rw-r--r--portable/uio.h12
-rw-r--r--tests/client/full-t.in8
-rw-r--r--tests/client/prompt-t.in12
-rw-r--r--tests/config/README24
-rw-r--r--tests/data/perl.conf6
-rwxr-xr-xtests/docs/pod-spelling-t108
-rwxr-xr-xtests/docs/pod-t52
-rw-r--r--tests/portable/asprintf-t.c13
-rw-r--r--tests/portable/mkstemp-t.c13
-rw-r--r--tests/portable/setenv-t.c16
-rw-r--r--tests/portable/snprintf-t.c18
-rw-r--r--tests/portable/strlcat-t.c16
-rw-r--r--tests/portable/strlcpy-t.c16
-rw-r--r--tests/runtests.c165
-rw-r--r--tests/tap/basic.c239
-rw-r--r--tests/tap/basic.h81
-rw-r--r--tests/tap/kerberos.c499
-rw-r--r--tests/tap/kerberos.h115
-rw-r--r--tests/tap/kerberos.sh64
-rw-r--r--tests/tap/libtap.sh192
-rw-r--r--tests/tap/macros.h88
-rw-r--r--tests/tap/messages.c49
-rw-r--r--tests/tap/messages.h30
-rw-r--r--tests/tap/perl/Test/RRA.pm222
-rw-r--r--tests/tap/perl/Test/RRA/Automake.pm362
-rw-r--r--tests/tap/perl/Test/RRA/Config.pm200
-rw-r--r--tests/tap/process.c125
-rw-r--r--tests/tap/process.h52
-rw-r--r--tests/tap/remctl.sh61
-rw-r--r--tests/tap/string.c65
-rw-r--r--tests/tap/string.h49
-rw-r--r--tests/util/messages-krb5-t.c41
-rw-r--r--tests/util/messages-t.c126
-rwxr-xr-xtests/util/xmalloc-t130
-rw-r--r--tests/util/xmalloc.c72
-rw-r--r--util/macros.h21
-rw-r--r--util/messages-krb5.c50
-rw-r--r--util/messages-krb5.h23
-rw-r--r--util/messages.c26
-rw-r--r--util/messages.h37
-rw-r--r--util/xmalloc.c62
-rw-r--r--util/xmalloc.h27
67 files changed, 3603 insertions, 890 deletions
diff --git a/.gitignore b/.gitignore
index d5ae8a0..23ffe53 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,11 +22,9 @@
/tests/client/full-t
/tests/client/prompt-t
/tests/client/rekey-t
-/tests/data/.placeholder
-/tests/data/test.keytab
-/tests/data/test.password
-/tests/data/test.principal
-/tests/data/test.krbtype
+/tests/config/keytab
+/tests/config/password
+/tests/config/principal
/tests/portable/asprintf-t
/tests/portable/mkstemp-t
/tests/portable/setenv-t
diff --git a/Makefile.am b/Makefile.am
index 0e1d99c..772a71e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,7 +26,6 @@ PERL_FILES = perl/Wallet/ACL.pm perl/Wallet/ACL/Base.pm \
perl/t/schema.t perl/t/server.t perl/t/verifier-netdb.t \
perl/t/verifier.t
-AUTOMAKE_OPTIONS = foreign subdir-objects
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = .gitignore LICENSE autogen client/wallet.pod \
client/wallet-rekey.pod config/allow-extract config/keytab \
@@ -97,18 +96,22 @@ dist_pkgdata_DATA = perl/sql/Wallet-Schema-0.07-0.08-MySQL.sql \
#
# -Wconversion http://bugs.debian.org/488884 (htons warnings)
#
-# Last checked against gcc 4.4 (2010-08-15).
-WARNINGS = -g -O -Wall -Wextra -Wendif-labels -Wformat=2 -Winit-self \
- -Wswitch-enum -Wdeclaration-after-statement -Wshadow -Wpointer-arith \
- -Wbad-function-cast -Wwrite-strings -Wstrict-prototypes \
- -Wmissing-prototypes -Wnested-externs -Werror
+# Last checked against gcc 4.6.1 (2011-05-04). -D_FORTIFY_SOURCE=2 enables
+# warn_unused_result attribute markings on glibc functions on Linux, which
+# catches a few more issues.
+WARNINGS = -g -O -D_FORTIFY_SOURCE=2 -Wall -Wextra -Wendif-labels \
+ -Wformat=2 -Winit-self -Wswitch-enum -Wdeclaration-after-statement \
+ -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align \
+ -Wwrite-strings -Wjump-misses-init -Wlogical-op \
+ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls \
+ -Wnested-externs -Werror
warnings:
$(MAKE) V=0 CFLAGS='$(WARNINGS)'
$(MAKE) V=0 CFLAGS='$(WARNINGS)' $(check_PROGRAMS)
# Remove some additional files.
-DISTCLEANFILES = perl/Makefile tests/data/.placeholder
+DISTCLEANFILES = perl/Makefile
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 build-aux/compile \
build-aux/depcomp build-aux/install-sh build-aux/missing \
client/wallet.1 config.h.in config.h.in~ configure \
@@ -163,7 +166,8 @@ check_LIBRARIES = tests/tap/libtap.a
tests_tap_libtap_a_CPPFLAGS = -I$(abs_top_srcdir)/tests $(KRB5_CPPFLAGS)
tests_tap_libtap_a_SOURCES = tests/tap/basic.c tests/tap/basic.h \
tests/tap/kerberos.c tests/tap/kerberos.h tests/tap/messages.c \
- tests/tap/messages.h tests/tap/process.c tests/tap/process.h
+ tests/tap/messages.h tests/tap/process.c tests/tap/process.h \
+ tests/tap/string.c tests/tap/string.h
# All of the test programs.
tests_portable_asprintf_t_SOURCES = tests/portable/asprintf-t.c \
diff --git a/NEWS b/NEWS
index b948d91..0d98220 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,49 @@ wallet 1.0 (unreleased)
Add docs/objects-and-schemes, which provides a brief summary of the
current supported object types and ACL schemes.
+ Update to rra-c-util 4.8:
+
+ * Look for krb5-config in /usr/kerberos/bin after the user's PATH.
+ * Kerberos library probing fixes without transitive shared libraries.
+ * Fix Autoconf warnings when probing for AIX's bundled Kerberos.
+ * Avoid using krb5-config if --with-{krb5,gssapi}-{include,lib} given.
+ * Correctly remove -I/usr/include from Kerberos and GSS-API flags.
+ * Build on systems where krb5/krb5.h exists but krb5.h does not.
+ * Pass --deps to krb5-config unless --enable-reduced-depends was used.
+ * Do not use krb5-config results unless gssapi is supported.
+ * Fix probing for Heimdal's libroken to work with older versions.
+ * Update warning flags for GCC 4.6.1.
+ * Update utility library and test suite for newer GCC warnings.
+ * Fix broken GCC attribute markers causing compilation problems.
+ * Suppress warnings on compilers that support gcc's __attribute__.
+ * Add notices to all files copied over from rra-c-util.
+ * Fix warnings when reporting memory allocation failure in messages.c.
+ * Fix message utility library compiler warnings on 64-bit systems.
+ * Include strings.h for additional POSIX functions where found.
+ * Use an atexit handler to clean up after Kerberos tests.
+ * Kerberos test configuration now goes in tests/config.
+ * The principal of the test keytab is determined automatically.
+ * Simplify the test suite calls for Kerberos and remctl tests.
+ * Check for a missing ssize_t.
+ * Improve the xstrndup utility function.
+ * Checked asprintf variants are now void functions and cannot fail.
+ * Fix use of long long in portable/mkstemp.c.
+ * Fix test suite portability to Solaris.
+ * Substantial improvements to the POD syntax and spelling checks.
+
+ Update to C TAP Harness 1.12:
+
+ * Fix compliation of runtests with more aggressive warnings.
+ * Add a more complete usage message and a -h command-line flag.
+ * Flush stderr before printing output from tests.
+ * Better handle running shell tests without BUILD and SOURCE set.
+ * Fix runtests to honor -s even if BUILD and -b aren't given.
+ * runtests now frees all allocated resources on exit.
+ * Only use feature-test macros when requested or built with gcc -ansi.
+ * Drop is_double from the C TAP library to avoid requiring -lm.
+ * Avoid using local in the shell libtap.sh library.
+ * Suppress warnings on compilers that support gcc's __attribute__.
+
wallet 0.12 (2010-08-25)
New client program wallet-rekey that, given a list of keytabs on the
diff --git a/README b/README
index c440b8c..b714098 100644
--- a/README
+++ b/README
@@ -223,7 +223,7 @@ TESTING
support in the server, however, you will need to do some preparatory
work before running the test suite. Review the files:
- tests/data/README
+ tests/config/README
perl/t/data/README
and follow the instructions in those files to enable the full test
diff --git a/configure.ac b/configure.ac
index ffd7eeb..a79e42d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,8 @@ AC_INIT([wallet], [0.12], [rra@stanford.edu])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_LIBOBJ_DIR([portable])
AC_CONFIG_MACRO_DIR([m4])
-AM_INIT_AUTOMAKE([1.11 check-news silent-rules])
+AM_INIT_AUTOMAKE([1.11 check-news dist-xz foreign silent-rules subdir-objects
+ -Wall -Wno-override -Werror])
AM_MAINTAINER_MODE
AC_PROG_CC
@@ -22,6 +23,18 @@ AM_PROG_CC_C_O
AC_PROG_INSTALL
AC_PROG_RANLIB
+AC_ARG_WITH([wallet-server],
+ [AC_HELP_STRING([--with-wallet-server=HOST], [Default wallet server])],
+ [AS_IF([test x"$withval" != xno && test x"$withval" != xyes],
+ [AC_DEFINE_UNQUOTED([WALLET_SERVER], ["$withval"],
+ [Define to the default server host name.])])])
+AC_ARG_WITH([wallet-port],
+ [AC_HELP_STRING([--with-wallet-port=PORT],
+ [Default wallet server port])],
+ [AS_IF([test x"$withval" != xno && test x"$withval" != xyes],
+ [AC_DEFINE_UNQUOTED([WALLET_PORT], [$withval],
+ [Define to the default server port.])])])
+
RRA_LIB_REMCTL
RRA_LIB_KRB5
RRA_LIB_KRB5_SWITCH
@@ -30,8 +43,9 @@ AC_CHECK_FUNCS([krb5_get_init_creds_opt_alloc \
krb5_principal_get_realm])
AC_CHECK_FUNCS([krb5_get_init_creds_opt_free],
[RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS])
+AC_CHECK_DECLS([krb5_kt_free_entry], [], [], [RRA_INCLUDES_KRB5])
AC_CHECK_DECLS([krb5_kt_free_entry])
-AC_CHECK_MEMBERS([krb5_keytab_entry.keyblock], , , [#include <krb5.h>])
+AC_CHECK_MEMBERS([krb5_keytab_entry.keyblock], [], [], [RRA_INCLUDES_KRB5])
RRA_LIB_KRB5_RESTORE
AC_HEADER_STDBOOL
@@ -40,31 +54,18 @@ AC_CHECK_DECLS([snprintf, vsnprintf])
RRA_C_C99_VAMACROS
RRA_C_GNU_VAMACROS
AC_TYPE_LONG_LONG_INT
+AC_CHECK_TYPES([ssize_t], [], [],
+ [#include <sys/types.h>])
RRA_FUNC_SNPRINTF
AC_CHECK_FUNCS([setrlimit])
AC_REPLACE_FUNCS([asprintf mkstemp setenv strlcat strlcpy])
-AC_ARG_WITH([wallet-server],
- [AC_HELP_STRING([--with-wallet-server=HOST], [Default wallet server])],
- [AS_IF([test x"$withval" != xno && test x"$withval" != xyes],
- [AC_DEFINE_UNQUOTED([WALLET_SERVER], ["$withval"],
- [Define to the default server host name.])])])
-AC_ARG_WITH([wallet-port],
- [AC_HELP_STRING([--with-wallet-port=PORT],
- [Default wallet server port])],
- [AS_IF([test x"$withval" != xno && test x"$withval" != xyes],
- [AC_DEFINE_UNQUOTED([WALLET_PORT], [$withval],
- [Define to the default server port.])])])
-
AC_ARG_VAR([REMCTLD], [Path to the remctld binary])
AC_PATH_PROG([REMCTLD], [remctld], , [$PATH:/usr/sbin:/usr/local/sbin])
AS_IF([test x"$REMCTLD" != x],
[AC_DEFINE_UNQUOTED([PATH_REMCTLD], ["$REMCTLD"],
[Define to the full path to remctld to run remctl tests.])])
-dnl Create the tests/data directory for builds outside the source directory.
-AC_CONFIG_COMMANDS([tests/data/.placeholder], [touch tests/data/.placeholder])
-
AC_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile perl/Makefile.PL])
AC_CONFIG_FILES([tests/client/basic-t], [chmod +x tests/client/basic-t])
diff --git a/m4/gssapi.m4 b/m4/gssapi.m4
index 0a657ff..c596609 100644
--- a/m4/gssapi.m4
+++ b/m4/gssapi.m4
@@ -3,7 +3,8 @@ dnl
dnl Finds the compiler and linker flags for linking with GSS-API libraries.
dnl Provides the --with-gssapi, --with-gssapi-include, and --with-gssapi-lib
dnl configure option to specify a non-standard path to the GSS-API libraries.
-dnl Uses krb5-config where available unless reduced dependencies is requested.
+dnl Uses krb5-config where available unless reduced dependencies is requested
+dnl or --with-gssapi-include or --with-gssapi-lib are given.
dnl
dnl Provides the macro RRA_LIB_GSSAPI and sets the substitution variables
dnl GSSAPI_CPPFLAGS, GSSAPI_LDFLAGS, and GSSAPI_LIBS. Also provides
@@ -11,13 +12,34 @@ dnl RRA_LIB_GSSAPI_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the
dnl GSS-API libraries, saving the ecurrent values, and RRA_LIB_GSSAPI_RESTORE
dnl to restore those settings to before the last RRA_LIB_GSSAPI_SWITCH.
dnl
-dnl Depends on RRA_ENABLE_REDUCED_DEPENDS and RRA_SET_LDFLAGS.
+dnl Also provides RRA_INCLUDES_KRB5, which are the headers to include when
+dnl probing the Kerberos library properties.
+dnl
+dnl Depends on RRA_KRB5_CONFIG, RRA_ENABLE_REDUCED_DEPENDS, and
+dnl RRA_SET_LDFLAGS.
+dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
dnl
dnl Written by Russ Allbery <rra@stanford.edu>
-dnl Copyright 2005, 2006, 2007, 2008, 2009
-dnl Board of Trustees, Leland Stanford Jr. University
+dnl Copyright 2005, 2006, 2007, 2008, 2009, 2011, 2012
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
+
+dnl Headers to include when probing for Kerberos library properties.
+AC_DEFUN([RRA_INCLUDES_GSSAPI], [[
+#ifdef HAVE_GSSAPI_GSSAPI_H
+# include <gssapi/gssapi.h>
+#else
+# include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+# include <gssapi/gssapi_krb5.h>
+#endif
+]])
dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to
dnl versions that include the GSS-API flags. Used as a wrapper, with
@@ -68,18 +90,18 @@ AC_DEFUN([_RRA_LIB_GSSAPI_MANUAL],
[RRA_LIB_GSSAPI_SWITCH
rra_gssapi_extra=
LIBS=
- AC_SEARCH_LIBS([res_search], [resolv], ,
+ AC_SEARCH_LIBS([res_search], [resolv], [],
[AC_SEARCH_LIBS([__res_search], [resolv])])
AC_SEARCH_LIBS([gethostbyname], [nsl])
- AC_SEARCH_LIBS([socket], [socket], ,
- [AC_CHECK_LIB([nsl], [socket], [LIBS="-lnsl -lsocket $LIBS"], ,
+ AC_SEARCH_LIBS([socket], [socket], [],
+ [AC_CHECK_LIB([nsl], [socket], [LIBS="-lnsl -lsocket $LIBS"], [],
[-lsocket])])
AC_SEARCH_LIBS([crypt], [crypt])
+ AC_SEARCH_LIBS([roken_concat], [roken])
rra_gssapi_extra="$LIBS"
LIBS="$rra_gssapi_save_LIBS"
AC_CHECK_LIB([gssapi], [gss_import_name],
- [GSSAPI_LIBS="-lgssapi -lkrb5 -lasn1 -lroken -lcrypto -lcom_err"
- GSSAPI_LIBS="$GSSAPI_LIBS $rra_gssapi_extra"],
+ [GSSAPI_LIBS="-lgssapi -lkrb5 -lasn1 -lcrypto -lcom_err $rra_gssapi_extra"],
[AC_CHECK_LIB([krb5support], [krb5int_getspecific],
[rra_gssapi_extra="-lkrb5support $rra_gssapi_extra"],
[AC_CHECK_LIB([pthreads], [pthread_setspecific],
@@ -88,7 +110,7 @@ AC_DEFUN([_RRA_LIB_GSSAPI_MANUAL],
[rra_gssapi_pthread="-lpthread"])])
AC_CHECK_LIB([krb5support], [krb5int_setspecific],
[rra_gssapi_extra="-lkrb5support $rra_gssapi_extra"
- rra_gssapi_extra="$rra_gssapi_extra $rra_gssapi_pthread"], ,
+ rra_gssapi_extra="$rra_gssapi_extra $rra_gssapi_pthread"], [],
[$rra_gssapi_pthread])])
AC_CHECK_LIB([com_err], [error_message],
[rra_gssapi_extra="-lcom_err $rra_gssapi_extra"])
@@ -101,7 +123,7 @@ AC_DEFUN([_RRA_LIB_GSSAPI_MANUAL],
[GSSAPI_LIBS="-lgss"],
[AC_MSG_ERROR([cannot find usable GSS-API library])])],
[$rra_gssapi_extra])],
- [-lkrb5 -lasn1 -lroken -lcrypto -lcom_err $rra_gssapi_extra])
+ [-lkrb5 -lasn1 -lcrypto -lcom_err $rra_gssapi_extra])
RRA_LIB_GSSAPI_RESTORE])
dnl Sanity-check the results of krb5-config and be sure we can really link a
@@ -116,6 +138,44 @@ AC_DEFUN([_RRA_LIB_GSSAPI_CHECK],
_RRA_LIB_GSSAPI_PATHS
_RRA_LIB_GSSAPI_MANUAL])])
+dnl Determine GSS-API compiler and linker flags from krb5-config.
+AC_DEFUN([_RRA_LIB_GSSAPI_CONFIG],
+[RRA_KRB5_CONFIG([${rra_gssapi_root}], [gssapi], [GSSAPI],
+ [_RRA_LIB_GSSAPI_CHECK],
+ [_RRA_LIB_GSSAPI_PATHS
+ _RRA_LIB_GSSAPI_MANUAL])])
+
+dnl Check for a header using a file existence check rather than using
+dnl AC_CHECK_HEADERS. This is used if there were arguments to configure
+dnl specifying the GSS-API library path, since we may have one header in the
+dnl default include path and another under our explicitly-configured GSS-API
+dnl location.
+AC_DEFUN([_RRA_LIB_GSSAPI_CHECK_HEADER],
+[AC_MSG_CHECKING([for $1])
+ AS_IF([test -f "${rra_gssapi_incroot}/$1"],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), [1],
+ [Define to 1 if you have the <$1> header file.])
+ AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])])])
+
+dnl Determine the GSS-API header location and probe for some other
+dnl characteristics of the libraries. We use a file existence check rather
+dnl than letting the compiler probe for the right header location
+AC_DEFUN([_RRA_LIB_GSSAPI_EXTRA],
+[rra_gssapi_incroot=
+ AS_IF([test x"$rra_gssapi_includedir" != x],
+ [rra_gssapi_incroot="$rra_gssapi_includedir"],
+ [AS_IF([test x"$rra_gssapi_root" != x],
+ [rra_gssapi_incroot="${rra_gssapi_root}/include"])])
+ AS_IF([test x"$rra_gssapi_incroot" = x],
+ [AC_CHECK_HEADERS([gssapi/gssapi.h gssapi/gssapi_krb5.h])],
+ [_RRA_LIB_GSSAPI_CHECK_HEADER([gssapi/gssapi.h])
+ _RRA_LIB_GSSAPI_CHECK_HEADER([gssapi/gssapi_krb5.h])])
+ AC_CHECK_DECL([GSS_C_NT_USER_NAME],
+ [AC_DEFINE([HAVE_GSS_RFC_OIDS], 1,
+ [Define to 1 if the GSS-API library uses RFC-compliant OIDs.])], [],
+ [RRA_INCLUDES_GSSAPI])])
+
dnl The main macro.
AC_DEFUN([RRA_LIB_GSSAPI],
[AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS])
@@ -148,24 +208,12 @@ AC_DEFUN([RRA_LIB_GSSAPI],
AS_IF([test x"$rra_reduced_depends" = xtrue],
[_RRA_LIB_GSSAPI_PATHS
_RRA_LIB_GSSAPI_REDUCED],
- [AC_ARG_VAR([KRB5_CONFIG], [Path to krb5-config])
- AS_IF([test x"$rra_gssapi_root" != x && test -z "$KRB5_CONFIG"],
- [AS_IF([test -x "${rra_gssapi_root}/bin/krb5-config"],
- [KRB5_CONFIG="${rra_gssapi_root}/bin/krb5-config"])],
- [AC_PATH_PROG([KRB5_CONFIG], [krb5-config])])
- AS_IF([test x"$KRB5_CONFIG" != x && test -x "$KRB5_CONFIG"],
- [AC_CACHE_CHECK([for gssapi support in krb5-config],
- [rra_cv_lib_gssapi_config],
- [AS_IF(["$KRB5_CONFIG" 2>&1 | grep gssapi >/dev/null 2>&1],
- [rra_cv_lib_gssapi_config=yes],
- [rra_cv_lib_gssapi_config=no])])
- AS_IF([test "$rra_cv_lib_gssapi_config" = yes],
- [GSSAPI_CPPFLAGS=`"$KRB5_CONFIG" --cflags gssapi 2>/dev/null`
- GSSAPI_LIBS=`"$KRB5_CONFIG" --libs gssapi 2>/dev/null`],
- [GSSAPI_CPPFLAGS=`"$KRB5_CONFIG" --cflags 2>/dev/null`
- GSSAPI_LIBS=`"$KRB5_CONFIG" --libs 2>/dev/null`])
- GSSAPI_CPPFLAGS=`echo "$GSSAPI_CPPFLAGS" \
- | sed 's%-I/usr/include ?%%'`
- _RRA_LIB_GSSAPI_CHECK],
- [_RRA_LIB_GSSAPI_PATHS
- _RRA_LIB_GSSAPI_MANUAL])])])
+ [AS_IF([test x"$rra_gssapi_includedir" = x \
+ && test x"$rra_gssapi_libdir" = x],
+ [_RRA_LIB_GSSAPI_CONFIG],
+ [_RRA_LIB_GSSAPI_PATHS
+ _RRA_LIB_GSSAPI_MANUAL])])
+
+ RRA_LIB_GSSAPI_SWITCH
+ _RRA_LIB_GSSAPI_EXTRA
+ RRA_LIB_GSSAPI_RESTORE])
diff --git a/m4/krb5-config.m4 b/m4/krb5-config.m4
new file mode 100644
index 0000000..d73085f
--- /dev/null
+++ b/m4/krb5-config.m4
@@ -0,0 +1,101 @@
+dnl Use krb5-config to get link paths for Kerberos libraries.
+dnl
+dnl Provides one macro, RRA_KRB5_CONFIG, which attempts to get compiler and
+dnl linker flags for a library via krb5-config and sets the appropriate shell
+dnl variables. Defines the Autoconf variable PATH_KRB5_CONFIG, which can be
+dnl used to find the default path to krb5-config.
+dnl
+dnl Depends on RRA_ENABLE_REDUCED_DEPENDS.
+dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
+dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Copyright 2011, 2012
+dnl The Board of Trustees of the Leland Stanford Junior University
+dnl
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
+
+dnl Check for krb5-config in the user's path and set PATH_KRB5_CONFIG. This
+dnl is moved into a separate macro so that it can be loaded via AC_REQUIRE,
+dnl meaning it will only be run once even if we link with multiple krb5-config
+dnl libraries.
+AC_DEFUN([_RRA_KRB5_CONFIG_PATH],
+[AC_ARG_VAR([PATH_KRB5_CONFIG], [Path to krb5-config])
+ AC_PATH_PROG([PATH_KRB5_CONFIG], [krb5-config], [],
+ [${PATH}:/usr/kerberos/bin])])
+
+dnl Check whether the --deps flag is supported by krb5-config. Takes the path
+dnl to krb5-config to use. Note that this path is not embedded in the cache
+dnl variable, so this macro implicitly assumes that we will always use the
+dnl same krb5-config program.
+AC_DEFUN([_RRA_KRB5_CONFIG_DEPS],
+[AC_REQUIRE([_RRA_KRB5_CONFIG_PATH])
+ AC_CACHE_CHECK([for --deps support in krb5-config],
+ [rra_cv_krb5_config_deps],
+ [AS_IF(["$1" 2>&1 | grep deps >/dev/null 2>&1],
+ [rra_cv_krb5_config_deps=yes],
+ [rra_cv_krb5_config_deps=no])])])
+
+dnl Obtain the library flags for a particular library using krb5-config.
+dnl Takes the path to the krb5-config program to use, the argument to
+dnl krb5-config to use, and the variable prefix under which to store the
+dnl library flags.
+AC_DEFUN([_RRA_KRB5_CONFIG_LIBS],
+[AC_REQUIRE([_RRA_KRB5_CONFIG_PATH])
+ AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS])
+ _RRA_KRB5_CONFIG_DEPS([$1])
+ AS_IF([test x"$rra_reduced_depends" = xfalse \
+ && test x"$rra_cv_krb5_config_deps" = xyes],
+ [$3[]_LIBS=`"$1" --deps --libs $2 2>/dev/null`],
+ [$3[]_LIBS=`"$1" --libs $2 2>/dev/null`])])
+
+dnl Attempt to find the flags for a library using krb5-config. Takes the
+dnl following arguments (in order):
+dnl
+dnl 1. The root directory for the library in question, generally from an
+dnl Autoconf --with flag. Used by preference as the path to krb5-config.
+dnl
+dnl 2. The argument to krb5-config to retrieve flags for this particular
+dnl library.
+dnl
+dnl 3. The variable prefix to use when setting CPPFLAGS and LIBS variables
+dnl based on the result of krb5-config.
+dnl
+dnl 4. Further actions to take if krb5-config was found and supported that
+dnl library type.
+dnl
+dnl 5. Further actions to take if krb5-config could not be used to get flags
+dnl for that library type.
+dnl
+dnl Special-case a krb5-config argument of krb5 and run krb5-config without an
+dnl argument if that option was requested and not supported. Old versions of
+dnl krb5-config didn't take an argument to specify the library type, but
+dnl always returned the flags for libkrb5.
+AC_DEFUN([RRA_KRB5_CONFIG],
+[AC_REQUIRE([_RRA_KRB5_CONFIG_PATH])
+ rra_krb5_config_$3=
+ rra_krb5_config_$3[]_ok=
+ AS_IF([test x"$1" != x && test -x "$1/bin/krb5-config"],
+ [rra_krb5_config_$3="$1/bin/krb5-config"],
+ [rra_krb5_config_$3="$PATH_KRB5_CONFIG"])
+ AS_IF([test x"$rra_krb5_config_$3" != x && test -x "$rra_krb5_config_$3"],
+ [AC_CACHE_CHECK([for $2 support in krb5-config], [rra_cv_lib_$3[]_config],
+ [AS_IF(["$rra_krb5_config_$3" 2>&1 | grep $2 >/dev/null 2>&1],
+ [rra_cv_lib_$3[]_config=yes],
+ [rra_cv_lib_$3[]_config=no])])
+ AS_IF([test "$rra_cv_lib_$3[]_config" = yes],
+ [$3[]_CPPFLAGS=`"$rra_krb5_config_$3" --cflags $2 2>/dev/null`
+ _RRA_KRB5_CONFIG_LIBS([$rra_krb5_config_$3], [$2], [$3])
+ rra_krb5_config_$3[]_ok=yes],
+ [AS_IF([test x"$2" = xkrb5],
+ [$3[]_CPPFLAGS=`"$rra_krb5_config_$3" --cflags 2>/dev/null`
+ $3[]_LIBS=`"$rra_krb5_config_$3" --libs $2 2>/dev/null`
+ rra_krb5_config_$3[]_ok=yes])])])
+ AS_IF([test x"$rra_krb5_config_$3[]_ok" = xyes],
+ [$3[]_CPPFLAGS=`echo "$$3[]_CPPFLAGS" | sed 's%-I/usr/include %%'`
+ $3[]_CPPFLAGS=`echo "$$3[]_CPPFLAGS" | sed 's%-I/usr/include$%%'`
+ $4],
+ [$5])])
diff --git a/m4/krb5.m4 b/m4/krb5.m4
index 38a050e..964023a 100644
--- a/m4/krb5.m4
+++ b/m4/krb5.m4
@@ -1,17 +1,18 @@
-dnl Find the compiler and linker flags for Kerberos v5.
+dnl Find the compiler and linker flags for Kerberos.
dnl
-dnl Finds the compiler and linker flags for linking with Kerberos v5
-dnl libraries. Provides the --with-krb5, --with-krb5-include, and
-dnl --with-krb5-lib configure options to specify non-standard paths to the
-dnl Kerberos libraries. Uses krb5-config where available unless reduced
-dnl dependencies is requested.
+dnl Finds the compiler and linker flags for linking with Kerberos libraries.
+dnl Provides the --with-krb5, --with-krb5-include, and --with-krb5-lib
+dnl configure options to specify non-standard paths to the Kerberos libraries.
+dnl Uses krb5-config where available unless reduced dependencies is requested
+dnl or --with-krb5-include or --with-krb5-lib are given.
dnl
dnl Provides the macro RRA_LIB_KRB5 and sets the substitution variables
dnl KRB5_CPPFLAGS, KRB5_LDFLAGS, and KRB5_LIBS. Also provides
dnl RRA_LIB_KRB5_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the
dnl Kerberos libraries, saving the current values first, and
dnl RRA_LIB_KRB5_RESTORE to restore those settings to before the last
-dnl RRA_LIB_KRB5_SWITCH.
+dnl RRA_LIB_KRB5_SWITCH. HAVE_KERBEROS will always be defined if RRA_LIB_KRB5
+dnl is used.
dnl
dnl If KRB5_CPPFLAGS, KRB5_LDFLAGS, or KRB5_LIBS are set before calling these
dnl macros, their values will be added to whatever the macros discover.
@@ -32,14 +33,31 @@ dnl Also provides RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS, which checks
dnl whether krb5_get_init_creds_opt_free takes one argument or two. Defines
dnl HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS if it takes two arguments.
dnl
+dnl Also provides RRA_INCLUDES_KRB5, which are the headers to include when
+dnl probing the Kerberos library properties.
+dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
dnl Written by Russ Allbery <rra@stanford.edu>
-dnl Copyright 2005, 2006, 2007, 2008, 2009, 2010
-dnl Board of Trustees, Leland Stanford Jr. University
+dnl Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
+
+dnl Headers to include when probing for Kerberos library properties.
+AC_DEFUN([RRA_INCLUDES_KRB5], [[
+#if HAVE_KRB5_H
+# include <krb5.h>
+#else
+# include <krb5/krb5.h>
+#endif
+]])
dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to
-dnl versions that include the Kerberos v5 flags. Used as a wrapper, with
+dnl versions that include the Kerberos flags. Used as a wrapper, with
dnl RRA_LIB_KRB5_RESTORE, around tests.
AC_DEFUN([RRA_LIB_KRB5_SWITCH],
[rra_krb5_save_CPPFLAGS="$CPPFLAGS"
@@ -69,44 +87,62 @@ AC_DEFUN([_RRA_LIB_KRB5_PATHS],
[AS_IF([test x"$rra_krb5_root" != x/usr],
[KRB5_CPPFLAGS="-I${rra_krb5_root}/include"])])])])
-dnl Does the appropriate library checks for reduced-dependency Kerberos v5
+dnl Check for a header using a file existence check rather than using
+dnl AC_CHECK_HEADERS. This is used if there were arguments to configure
+dnl specifying the Kerberos header path, since we may have one header in the
+dnl default include path and another under our explicitly-configured Kerberos
+dnl location.
+AC_DEFUN([_RRA_LIB_KRB5_CHECK_HEADER],
+[AC_MSG_CHECKING([for $1])
+ AS_IF([test -f "${rra_krb5_incroot}/$1"],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), [1],
+ [Define to 1 if you have the <$1> header file.])
+ AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])])])
+
+dnl Does the appropriate library checks for reduced-dependency Kerberos
dnl linkage. The single argument, if true, says to fail if Kerberos could not
dnl be found.
AC_DEFUN([_RRA_LIB_KRB5_REDUCED],
[RRA_LIB_KRB5_SWITCH
AC_CHECK_LIB([krb5], [krb5_init_context], [KRB5_LIBS="-lkrb5"],
[AS_IF([test x"$1" = xtrue],
- [AC_MSG_ERROR([cannot find usable Kerberos v5 library])])])
+ [AC_MSG_ERROR([cannot find usable Kerberos library])])])
LIBS="$KRB5_LIBS $LIBS"
+ AS_IF([test x"$rra_krb5_incroot" = x],
+ [AC_CHECK_HEADERS([krb5.h krb5/krb5.h])],
+ [_RRA_LIB_KRB5_CHECK_HEADER([krb5.h])
+ _RRA_LIB_KRB5_CHECK_HEADER([krb5/krb5.h])])
AC_CHECK_FUNCS([krb5_get_error_message],
[AC_CHECK_FUNCS([krb5_free_error_message])],
- [AC_CHECK_FUNCS([krb5_get_error_string], ,
- [AC_CHECK_FUNCS([krb5_get_err_txt], ,
+ [AC_CHECK_FUNCS([krb5_get_error_string], [],
+ [AC_CHECK_FUNCS([krb5_get_err_txt], [],
[AC_CHECK_LIB([ksvc], [krb5_svc_get_msg],
[KRB5_LIBS="$KRB5_LIBS -lksvc"
AC_DEFINE([HAVE_KRB5_SVC_GET_MSG], [1])
- AC_CHECK_HEADERS([ibm_svc/krb5_svc.h])],
+ AC_CHECK_HEADERS([ibm_svc/krb5_svc.h], [], [],
+ [RRA_INCLUDES_KRB5])],
[AC_CHECK_LIB([com_err], [com_err],
[KRB5_LIBS="$KRB5_LIBS -lcom_err"],
[AC_MSG_ERROR([cannot find usable com_err library])])
AC_CHECK_HEADERS([et/com_err.h])])])])])
RRA_LIB_KRB5_RESTORE])
-dnl Does the appropriate library checks for Kerberos v5 linkage when we don't
+dnl Does the appropriate library checks for Kerberos linkage when we don't
dnl have krb5-config or reduced dependencies. The single argument, if true,
dnl says to fail if Kerberos could not be found.
AC_DEFUN([_RRA_LIB_KRB5_MANUAL],
[RRA_LIB_KRB5_SWITCH
rra_krb5_extra=
LIBS=
- AC_SEARCH_LIBS([res_search], [resolv], ,
+ AC_SEARCH_LIBS([res_search], [resolv], [],
[AC_SEARCH_LIBS([__res_search], [resolv])])
AC_SEARCH_LIBS([gethostbyname], [nsl])
- AC_SEARCH_LIBS([socket], [socket], ,
- [AC_CHECK_LIB([nsl], [socket], [LIBS="-lnsl -lsocket $LIBS"], ,
+ AC_SEARCH_LIBS([socket], [socket], [],
+ [AC_CHECK_LIB([nsl], [socket], [LIBS="-lnsl -lsocket $LIBS"], [],
[-lsocket])])
AC_SEARCH_LIBS([crypt], [crypt])
- AC_SEARCH_LIBS([rk_simple_execve], [roken])
+ AC_SEARCH_LIBS([roken_concat], [roken])
rra_krb5_extra="$LIBS"
LIBS="$rra_krb5_save_LIBS"
AC_CHECK_LIB([krb5], [krb5_init_context],
@@ -119,28 +155,34 @@ AC_DEFUN([_RRA_LIB_KRB5_MANUAL],
[rra_krb5_pthread="-lpthread"])])
AC_CHECK_LIB([krb5support], [krb5int_setspecific],
[rra_krb5_extra="-lkrb5support $rra_krb5_extra $rra_krb5_pthread"],
- , [$rra_krb5_pthread])])
+ [], [$rra_krb5_pthread $rra_krb5_extra])],
+ [$rra_krb5_extra])
AC_CHECK_LIB([com_err], [error_message],
- [rra_krb5_extra="-lcom_err $rra_krb5_extra"])
+ [rra_krb5_extra="-lcom_err $rra_krb5_extra"], [], [$rra_krb5_extra])
AC_CHECK_LIB([ksvc], [krb5_svc_get_msg],
- [rra_krb5_extra="-lksvc $rra_krb5_extra"])
+ [rra_krb5_extra="-lksvc $rra_krb5_extra"], [], [$rra_krb5_extra])
AC_CHECK_LIB([k5crypto], [krb5int_hash_md5],
- [rra_krb5_extra="-lk5crypto $rra_krb5_extra"])
+ [rra_krb5_extra="-lk5crypto $rra_krb5_extra"], [], [$rra_krb5_extra])
AC_CHECK_LIB([k5profile], [profile_get_values],
- [rra_krb5_extra="-lk5profile $rra_krb5_extra"])
+ [rra_krb5_extra="-lk5profile $rra_krb5_extra"], [], [$rra_krb5_extra])
AC_CHECK_LIB([krb5], [krb5_cc_default],
[KRB5_LIBS="-lkrb5 $rra_krb5_extra"],
[AS_IF([test x"$1" = xtrue],
- [AC_MSG_ERROR([cannot find usable Kerberos v5 library])])],
+ [AC_MSG_ERROR([cannot find usable Kerberos library])])],
[$rra_krb5_extra])],
[-lasn1 -lcom_err -lcrypto $rra_krb5_extra])
LIBS="$KRB5_LIBS $LIBS"
+ AS_IF([test x"$rra_krb5_incroot" = x],
+ [AC_CHECK_HEADERS([krb5.h krb5/krb5.h])],
+ [_RRA_LIB_KRB5_CHECK_HEADER([krb5.h])
+ _RRA_LIB_KRB5_CHECK_HEADER([krb5/krb5.h])])
AC_CHECK_FUNCS([krb5_get_error_message],
[AC_CHECK_FUNCS([krb5_free_error_message])],
- [AC_CHECK_FUNCS([krb5_get_error_string], ,
- [AC_CHECK_FUNCS([krb5_get_err_txt], ,
+ [AC_CHECK_FUNCS([krb5_get_error_string], [],
+ [AC_CHECK_FUNCS([krb5_get_err_txt], [],
[AC_CHECK_FUNCS([krb5_svc_get_msg],
- [AC_CHECK_HEADERS([ibm_svc/krb5_svc.h])],
+ [AC_CHECK_HEADERS([ibm_svc/krb5_svc.h], [], [],
+ [RRA_INCLUDES_KRB5])],
[AC_CHECK_HEADERS([et/com_err.h])])])])])
RRA_LIB_KRB5_RESTORE])
@@ -158,49 +200,49 @@ AC_DEFUN([_RRA_LIB_KRB5_CHECK],
_RRA_LIB_KRB5_PATHS
_RRA_LIB_KRB5_MANUAL([$1])])])
+dnl Determine Kerberos compiler and linker flags from krb5-config. Does the
+dnl additional probing we need to do to uncover error handling features, and
+dnl falls back on the manual checks.
+AC_DEFUN([_RRA_LIB_KRB5_CONFIG],
+[RRA_KRB5_CONFIG([${rra_krb5_root}], [krb5], [KRB5],
+ [_RRA_LIB_KRB5_CHECK([$1])
+ RRA_LIB_KRB5_SWITCH
+ AS_IF([test x"$rra_krb5_incroot" = x],
+ [AC_CHECK_HEADERS([krb5.h krb5/krb5.h])],
+ [_RRA_LIB_KRB5_CHECK_HEADER([krb5.h])
+ _RRA_LIB_KRB5_CHECK_HEADER([krb5/krb5.h])])
+ AC_CHECK_FUNCS([krb5_get_error_message],
+ [AC_CHECK_FUNCS([krb5_free_error_message])],
+ [AC_CHECK_FUNCS([krb5_get_error_string], [],
+ [AC_CHECK_FUNCS([krb5_get_err_txt], [],
+ [AC_CHECK_FUNCS([krb5_svc_get_msg],
+ [AC_CHECK_HEADERS([ibm_svc/krb5_svc.h], [], [],
+ [RRA_INCLUDES_KRB5])],
+ [AC_CHECK_HEADERS([et/com_err.h])])])])])
+ RRA_LIB_KRB5_RESTORE],
+ [_RRA_LIB_KRB5_PATHS
+ _RRA_LIB_KRB5_MANUAL([$1])])])
+
dnl The core of the library checking, shared between RRA_LIB_KRB5 and
dnl RRA_LIB_KRB5_OPTIONAL. The single argument, if "true", says to fail if
-dnl Kerberos could not be found.
+dnl Kerberos could not be found. Set up rra_krb5_incroot for later header
+dnl checking.
AC_DEFUN([_RRA_LIB_KRB5_INTERNAL],
[AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS])
+ rra_krb5_incroot=
+ AS_IF([test x"$rra_krb5_includedir" != x],
+ [rra_krb5_incroot="$rra_krb5_includedir"],
+ [AS_IF([test x"$rra_krb5_root" != x],
+ [rra_krb5_incroot="${rra_krb5_root}/include"])])
AS_IF([test x"$rra_reduced_depends" = xtrue],
[_RRA_LIB_KRB5_PATHS
_RRA_LIB_KRB5_REDUCED([$1])],
- [AC_ARG_VAR([KRB5_CONFIG], [Path to krb5-config])
- AS_IF([test x"$rra_krb5_root" != x && test -z "$KRB5_CONFIG"],
- [AS_IF([test -x "${rra_krb5_root}/bin/krb5-config"],
- [KRB5_CONFIG="${rra_krb5_root}/bin/krb5-config"])],
- [AC_PATH_PROG([KRB5_CONFIG], [krb5-config])])
- AS_IF([test x"$KRB5_CONFIG" != x && test -x "$KRB5_CONFIG"],
- [AC_CACHE_CHECK([for krb5 support in krb5-config],
- [rra_cv_lib_krb5_config],
- [AS_IF(["$KRB5_CONFIG" 2>&1 | grep krb5 >/dev/null 2>&1],
- [rra_cv_lib_krb5_config=yes],
- [rra_cv_lib_krb5_config=no])])
- AS_IF([test x"$rra_cv_lib_krb5_config" = xyes],
- [KRB5_CPPFLAGS=`"$KRB5_CONFIG" --cflags krb5 2>/dev/null`
- KRB5_LIBS=`"$KRB5_CONFIG" --libs krb5 2>/dev/null`],
- [KRB5_CPPFLAGS=`"$KRB5_CONFIG" --cflags 2>/dev/null`
- KRB5_LIBS=`"$KRB5_CONFIG" --libs 2>/dev/null`])
- KRB5_CPPFLAGS=`echo "$KRB5_CPPFLAGS" | sed 's%-I/usr/include ?%%'`
- _RRA_LIB_KRB5_CHECK([$1])
- RRA_LIB_KRB5_SWITCH
- AC_CHECK_FUNCS([krb5_get_error_message],
- [AC_CHECK_FUNCS([krb5_free_error_message])],
- [AC_CHECK_FUNCS([krb5_get_error_string], ,
- [AC_CHECK_FUNCS([krb5_get_err_txt], ,
- [AC_CHECK_FUNCS([krb5_svc_get_msg],
- [AC_CHECK_HEADERS([ibm_svc/krb5_svc.h])],
- [AC_CHECK_HEADERS([et/com_err.h])])])])])
- RRA_LIB_KRB5_RESTORE],
- [_RRA_LIB_KRB5_PATHS
- _RRA_LIB_KRB5_MANUAL([$1])])])
+ [AS_IF([test x"$rra_krb5_includedir" = x && test x"$rra_krb5_libdir" = x],
+ [_RRA_LIB_KRB5_CONFIG([$1])],
+ [_RRA_LIB_KRB5_PATHS
+ _RRA_LIB_KRB5_MANUAL([$1])])])
rra_krb5_uses_com_err=false
- case "$LIBS" in
- *-lcom_err*)
- rra_krb5_uses_com_err=true
- ;;
- esac
+ AS_CASE([$LIBS], [*-lcom_err*], [rra_krb5_uses_com_err=true])
AM_CONDITIONAL([KRB5_USES_COM_ERR], [test x"$rra_krb5_uses_com_err" = xtrue])])
dnl The main macro for packages with mandatory Kerberos support.
@@ -208,26 +250,28 @@ AC_DEFUN([RRA_LIB_KRB5],
[rra_krb5_root=
rra_krb5_libdir=
rra_krb5_includedir=
+ rra_use_kerberos=true
AC_SUBST([KRB5_CPPFLAGS])
AC_SUBST([KRB5_LDFLAGS])
AC_SUBST([KRB5_LIBS])
AC_ARG_WITH([krb5],
[AS_HELP_STRING([--with-krb5=DIR],
- [Location of Kerberos v5 headers and libraries])],
+ [Location of Kerberos headers and libraries])],
[AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
[rra_krb5_root="$withval"])])
AC_ARG_WITH([krb5-include],
[AS_HELP_STRING([--with-krb5-include=DIR],
- [Location of Kerberos v5 headers])],
+ [Location of Kerberos headers])],
[AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
[rra_krb5_includedir="$withval"])])
AC_ARG_WITH([krb5-lib],
[AS_HELP_STRING([--with-krb5-lib=DIR],
- [Location of Kerberos v5 libraries])],
+ [Location of Kerberos libraries])],
[AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
[rra_krb5_libdir="$withval"])])
- _RRA_LIB_KRB5_INTERNAL([true])])
+ _RRA_LIB_KRB5_INTERNAL([true])
+ AC_DEFINE([HAVE_KERBEROS], 1, [Define to enable Kerberos features.])])
dnl The main macro for packages with optional Kerberos support.
AC_DEFUN([RRA_LIB_KRB5_OPTIONAL],
@@ -241,29 +285,41 @@ AC_DEFUN([RRA_LIB_KRB5_OPTIONAL],
AC_ARG_WITH([krb5],
[AS_HELP_STRING([--with-krb5@<:@=DIR@:>@],
- [Location of Kerberos v5 headers and libraries])],
+ [Location of Kerberos headers and libraries])],
[AS_IF([test x"$withval" = xno],
[rra_use_kerberos=false],
[AS_IF([test x"$withval" != xyes], [rra_krb5_root="$withval"])
rra_use_kerberos=true])])
AC_ARG_WITH([krb5-include],
[AS_HELP_STRING([--with-krb5-include=DIR],
- [Location of Kerberos v5 headers])],
+ [Location of Kerberos headers])],
[AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
[rra_krb5_includedir="$withval"])])
AC_ARG_WITH([krb5-lib],
[AS_HELP_STRING([--with-krb5-lib=DIR],
- [Location of Kerberos v5 libraries])],
+ [Location of Kerberos libraries])],
[AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
[rra_krb5_libdir="$withval"])])
AS_IF([test x"$rra_use_kerberos" != xfalse],
[AS_IF([test x"$rra_use_kerberos" = xtrue],
[_RRA_LIB_KRB5_INTERNAL([true])],
- [_RRA_LIB_KRB5_INTERNAL([false])])])
+ [_RRA_LIB_KRB5_INTERNAL([false])])],
+ [AM_CONDITIONAL([KRB5_USES_COM_ERR], [false])])
AS_IF([test x"$KRB5_LIBS" != x],
[AC_DEFINE([HAVE_KERBEROS], 1, [Define to enable Kerberos features.])])])
+dnl Source used by RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS.
+AC_DEFUN([_RRA_FUNC_KRB5_OPT_FREE_ARGS_SOURCE], [RRA_INCLUDES_KRB5] [[
+int
+main(void)
+{
+ krb5_get_init_creds_opt *opts;
+ krb5_context c;
+ krb5_get_init_creds_opt_free(c, opts);
+}
+]])
+
dnl Check whether krb5_get_init_creds_opt_free takes one argument or two.
dnl Early Heimdal used to take a single argument. Defines
dnl HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS if it takes two arguments.
@@ -272,9 +328,7 @@ dnl Should be called with RRA_LIB_KRB5_SWITCH active.
AC_DEFUN([RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS],
[AC_CACHE_CHECK([if krb5_get_init_creds_opt_free takes two arguments],
[rra_cv_func_krb5_get_init_creds_opt_free_args],
- [AC_TRY_COMPILE([#include <krb5.h>],
- [krb5_get_init_creds_opt *opts; krb5_context c;
- krb5_get_init_creds_opt_free(c, opts);],
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_RRA_FUNC_KRB5_OPT_FREE_ARGS_SOURCE])],
[rra_cv_func_krb5_get_init_creds_opt_free_args=yes],
[rra_cv_func_krb5_get_init_creds_opt_free_args=no])])
AS_IF([test $rra_cv_func_krb5_get_init_creds_opt_free_args = yes],
diff --git a/m4/lib-depends.m4 b/m4/lib-depends.m4
index 039e245..b5185f3 100644
--- a/m4/lib-depends.m4
+++ b/m4/lib-depends.m4
@@ -9,11 +9,16 @@ dnl
dnl This macro doesn't do much but is defined separately so that other macros
dnl can require it with AC_REQUIRE.
dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
dnl Written by Russ Allbery <rra@stanford.edu>
dnl Copyright 2005, 2006, 2007
-dnl Board of Trustees, Leland Stanford Jr. University
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
AC_DEFUN([RRA_ENABLE_REDUCED_DEPENDS],
[rra_reduced_depends=false
diff --git a/m4/lib-pathname.m4 b/m4/lib-pathname.m4
index fc326a0..fd5a5a1 100644
--- a/m4/lib-pathname.m4
+++ b/m4/lib-pathname.m4
@@ -12,10 +12,16 @@ dnl
dnl This file also provides the Autoconf macro RRA_SET_LIBDIR, which sets the
dnl libdir variable to PREFIX/lib{,32,64} as appropriate.
dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
dnl Written by Russ Allbery <rra@stanford.edu>
-dnl Copyright 2008, 2009 Board of Trustees, Leland Stanford Jr. University
+dnl Copyright 2008, 2009
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
dnl Probe for the alternate library name that we should attempt on this
dnl architecture, given the size of an int, and set rra_lib_arch_name to that
diff --git a/m4/remctl.m4 b/m4/remctl.m4
index bb3a56f..588404f 100644
--- a/m4/remctl.m4
+++ b/m4/remctl.m4
@@ -10,15 +10,28 @@ dnl REMCTL_CPPFLAGS, REMCTL_LDFLAGS, and REMCTL_LIBS. Also provides
dnl RRA_LIB_REMCTL_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the
dnl remctl libraries, saving the current values first, and
dnl RRA_LIB_REMCTL_RESTORE to restore those settings to before the last
-dnl RRA_LIB_REMCTL_SWITCH.
+dnl RRA_LIB_REMCTL_SWITCH. HAVE_REMCTL will always be defined if
+dnl RRA_LIB_REMCTL is used.
+dnl
+dnl Provides the RRA_LIB_REMCTL_OPTIONAL macro, which should be used if
+dnl Kerberos support is optional. This macro will still always est the
+dnl substitution variables, but they'll be empty unless --with-remctl is
+dnl given. HAVE_REMCTL will be defined if --with-remctl is given and
+dnl $rra_use_remctl will be set to "true".
dnl
dnl Depends on RRA_ENABLE_REDUCED_DEPENDS, RRA_SET_LDFLAGS, and
dnl RRA_LIB_GSSAPI.
dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
dnl Written by Russ Allbery <rra@stanford.edu>
-dnl Copyright 2008, 2009 Board of Trustees, Leland Stanford Jr. University
+dnl Copyright 2008, 2009, 2011
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to
dnl versions that include the remctl flags. Used as a wrapper, with
@@ -55,16 +68,34 @@ dnl Sanity-check the results of the remctl library search to be sure we can
dnl really link a remctl program.
AC_DEFUN([_RRA_LIB_REMCTL_CHECK],
[RRA_LIB_REMCTL_SWITCH
- AC_CHECK_FUNC([remctl_open], ,
- [AC_MSG_FAILURE([unable to link with remctl library])])
+ AC_CHECK_FUNC([remctl_open], [],
+ [AS_IF([test x"$1" = xtrue],
+ [AC_MSG_FAILURE([unable to link with remctl library])])
+ REMCTL_CPPFLAGS=
+ REMCTL_LDFLAGS=
+ REMCTL_LIBS=])
RRA_LIB_REMCTL_RESTORE])
-dnl The main macro.
-AC_DEFUN([RRA_LIB_REMCTL],
+dnl The core of the library checking, shared between RRA_LIB_REMCTL and
+dnl RRA_LIB_REMCTL_OPTIONAL. The single argument, if "true", says to fail if
+dnl remctl could not be found.
+AC_DEFUN([_RRA_LIB_REMCTL_INTERNAL],
[AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS])
- rra_remctl_root=
+ _RRA_LIB_REMCTL_PATHS
+ AS_IF([test x"$rra_reduced_depends" = xtrue],
+ [REMCTL_LIBS="-lremctl"],
+ [RRA_LIB_GSSAPI
+ REMCTL_CPPFLAGS="$REMCTL_CPPFLAGS $GSSAPI_CPPFLAGS"
+ REMCTL_LDFLAGS="$REMCTL_LDFLAGS $GSSAPI_LDFLAGS"
+ REMCTL_LIBS="-lremctl $GSSAPI_LIBS"])
+ _RRA_LIB_REMCTL_CHECK([$1])])
+
+dnl The main macro for packages with mandatory remctl support.
+AC_DEFUN([RRA_LIB_REMCTL],
+[rra_remctl_root=
rra_remctl_libdir=
rra_remctl_includedir=
+ rra_use_remctl=true
REMCTL_CPPFLAGS=
REMCTL_LDFLAGS=
REMCTL_LIBS=
@@ -87,12 +118,43 @@ AC_DEFUN([RRA_LIB_REMCTL],
[Location of remctl libraries])],
[AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
[rra_remctl_libdir="$withval"])])
+ _RRA_LIB_REMCTL_INTERNAL([true])
+ AC_DEFINE([HAVE_REMCTL], 1, [Define to enable remctl features.])])
- _RRA_LIB_REMCTL_PATHS
- AS_IF([test x"$rra_reduced_depends" = xtrue],
- [REMCTL_LIBS="-lremctl"],
- [RRA_LIB_GSSAPI
- REMCTL_CPPFLAGS="$REMCTL_CPPFLAGS $GSSAPI_CPPFLAGS"
- REMCTL_LDFLAGS="$REMCTL_LDFLAGS $GSSAPI_LDFLAGS"
- REMCTL_LIBS="-lremctl $GSSAPI_LIBS"])
- _RRA_LIB_REMCTL_CHECK])
+dnl The main macro for packages with optional remctl support.
+AC_DEFUN([RRA_LIB_REMCTL_OPTIONAL],
+[rra_remctl_root=
+ rra_remctl_libdir=
+ rra_remctl_includedir=
+ rra_use_remctl=
+ REMCTL_CPPFLAGS=
+ REMCTL_LDFLAGS=
+ REMCTL_LIBS=
+ AC_SUBST([REMCTL_CPPFLAGS])
+ AC_SUBST([REMCTL_LDFLAGS])
+ AC_SUBST([REMCTL_LIBS])
+
+ AC_ARG_WITH([remctl],
+ [AS_HELP_STRING([--with-remctl@<:@=DIR@:>@],
+ [Location of remctl headers and libraries])],
+ [AS_IF([test x"$withval" = xno],
+ [rra_use_remctl=false],
+ [AS_IF([test x"$withval" != xyes], [rra_remctl_root="$withval"])
+ rra_use_remctl=true])])
+ AC_ARG_WITH([remctl-include],
+ [AS_HELP_STRING([--with-remctl-include=DIR],
+ [Location of remctl headers])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_remctl_includedir="$withval"])])
+ AC_ARG_WITH([remctl-lib],
+ [AS_HELP_STRING([--with-remctl-lib=DIR],
+ [Location of remctl libraries])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_remctl_libdir="$withval"])])
+ AS_IF([test x"$rra_use_remctl" != xfalse],
+ [AS_IF([test x"$rra_use_remctl" = xtrue],
+ [_RRA_LIB_REMCTL_INTERNAL([true])],
+ [_RRA_LIB_REMCTL_INTERNAL([false])])])
+ AS_IF([test x"$REMCTL_LIBS" != x],
+ [rra_use_remctl=true
+ AC_DEFINE([HAVE_REMCTL], 1, [Define to enable remctl features.])])])
diff --git a/m4/snprintf.m4 b/m4/snprintf.m4
index d933f55..cd585ef 100644
--- a/m4/snprintf.m4
+++ b/m4/snprintf.m4
@@ -9,11 +9,16 @@ dnl
dnl Provides RRA_FUNC_SNPRINTF, which adds snprintf.o to LIBOBJS unless a
dnl fully working snprintf is found.
dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
dnl Written by Russ Allbery <rra@stanford.edu>
dnl Copyright 2006, 2008, 2009
-dnl Board of Trustees, Leland Stanford Jr. University
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
dnl Source used by RRA_FUNC_SNPRINTF.
AC_DEFUN([_RRA_FUNC_SNPRINTF_SOURCE], [[
diff --git a/m4/vamacros.m4 b/m4/vamacros.m4
index 855bb40..af98f6a 100644
--- a/m4/vamacros.m4
+++ b/m4/vamacros.m4
@@ -13,11 +13,16 @@ dnl #define macro(args...) fprintf(stderr, args)
dnl
dnl They set HAVE_C99_VAMACROS or HAVE_GNU_VAMACROS as appropriate.
dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
dnl Written by Russ Allbery <rra@stanford.edu>
dnl Copyright 2006, 2008, 2009
-dnl Board of Trustees, Leland Stanford Jr. University
+dnl The Board of Trustees of the Leland Stanford Junior University
dnl
-dnl See LICENSE for licensing terms.
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
AC_DEFUN([_RRA_C_C99_VAMACROS_SOURCE], [[
#include <stdio.h>
diff --git a/portable/asprintf.c b/portable/asprintf.c
index 4219a19..0093070 100644
--- a/portable/asprintf.c
+++ b/portable/asprintf.c
@@ -4,8 +4,18 @@
* Provides the same functionality as the standard GNU library routines
* asprintf and vasprintf for those platforms that don't have them.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/portable/dummy.c b/portable/dummy.c
index 8a0d54d..50052ec 100644
--- a/portable/dummy.c
+++ b/portable/dummy.c
@@ -5,8 +5,18 @@
* supply, Automake builds an empty library and then calls ar with nonsensical
* arguments. Ensure that libportable always contains at least one symbol.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
/* Prototype to avoid gcc warnings. */
diff --git a/portable/krb5-extra.c b/portable/krb5-extra.c
index 89ccbde..849842c 100644
--- a/portable/krb5-extra.c
+++ b/portable/krb5-extra.c
@@ -6,8 +6,18 @@
* Everything in this file will be protected by #ifndef. If the native
* Kerberos libraries are fully capable, this file will be skipped.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/portable/krb5.h b/portable/krb5.h
index 3b5700b..b418ae7 100644
--- a/portable/krb5.h
+++ b/portable/krb5.h
@@ -16,8 +16,18 @@
* prefers the generic krb5_xfree(). In this case, this header provides
* krb5_free_unparsed_name() for both APIs since it's the most specific call.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#ifndef PORTABLE_KRB5_H
@@ -32,7 +42,11 @@
#endif
#include <portable/macros.h>
-#include <krb5.h>
+#ifdef HAVE_KRB5_H
+# include <krb5.h>
+#else
+# include <krb5/krb5.h>
+#endif
#include <stdlib.h>
BEGIN_DECLS
@@ -75,7 +89,7 @@ krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context,
/* Heimdal-specific. */
#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS
-#define krb5_get_init_creds_opt_set_default_flags(c, p, r, o) /* empty */
+# define krb5_get_init_creds_opt_set_default_flags(c, p, r, o) /* empty */
#endif
/*
diff --git a/portable/macros.h b/portable/macros.h
index 8d5adbd..b33d064 100644
--- a/portable/macros.h
+++ b/portable/macros.h
@@ -1,8 +1,18 @@
/*
* Portability macros used in include files.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#ifndef PORTABLE_MACROS_H
@@ -20,6 +30,29 @@
#endif
/*
+ * We use __alloc_size__, but it was only available in fairly recent versions
+ * of GCC. Suppress warnings about the unknown attribute if GCC is too old.
+ * We know that we're GCC at this point, so we can use the GCC variadic macro
+ * extension, which will still work with versions of GCC too old to have C99
+ * variadic macro support.
+ */
+#if !defined(__attribute__) && !defined(__alloc_size__)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
+# define __alloc_size__(spec, args...) /* empty */
+# endif
+#endif
+
+/*
+ * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
+ * settings that GCC does. For them, suppress warnings about unknown
+ * attributes on declarations. This unfortunately will affect the entire
+ * compilation context, but there's no push and pop available.
+ */
+#if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__))
+# pragma GCC diagnostic ignored "-Wattributes"
+#endif
+
+/*
* BEGIN_DECLS is used at the beginning of declarations so that C++
* compilers don't mangle their names. END_DECLS is used at the end.
*/
diff --git a/portable/mkstemp.c b/portable/mkstemp.c
index dd2a485..8668db1 100644
--- a/portable/mkstemp.c
+++ b/portable/mkstemp.c
@@ -4,8 +4,18 @@
* Provides the same functionality as the library function mkstemp for those
* systems that don't have it.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
@@ -27,7 +37,7 @@ int test_mkstemp(char *);
#endif
/* Pick the longest available integer type. */
-#if HAVE_LONG_LONG
+#if HAVE_LONG_LONG_INT
typedef unsigned long long long_int_type;
#else
typedef unsigned long long_int_type;
diff --git a/portable/setenv.c b/portable/setenv.c
index d66ddcd..fd2b10c 100644
--- a/portable/setenv.c
+++ b/portable/setenv.c
@@ -4,8 +4,18 @@
* Provides the same functionality as the standard library routine setenv for
* those platforms that don't have it.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
@@ -31,10 +41,9 @@ setenv(const char *name, const char *value, int overwrite)
/*
* Allocate memory for the environment string. We intentionally don't use
- * concat here, or the xmalloc family of allocation routines, since the
- * intention is to provide a replacement for the standard library function
- * which sets errno and returns in the event of a memory allocation
- * failure.
+ * the xmalloc family of allocation routines here, since the intention is
+ * to provide a replacement for the standard library function that sets
+ * errno and returns in the event of a memory allocation failure.
*/
size = strlen(name) + 1 + strlen(value) + 1;
envstring = malloc(size);
diff --git a/portable/snprintf.c b/portable/snprintf.c
index ab3121c..91c8491 100644
--- a/portable/snprintf.c
+++ b/portable/snprintf.c
@@ -8,6 +8,9 @@
* Please do not reformat or otherwise change this file more than necessary so
* that later merges with the original source are easy. Bug fixes and
* improvements should be sent back to the original author.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*/
/*
diff --git a/portable/stdbool.h b/portable/stdbool.h
index bfbf4c4..045436f 100644
--- a/portable/stdbool.h
+++ b/portable/stdbool.h
@@ -5,13 +5,31 @@
* following the C99 specification, on hosts that don't have stdbool.h. This
* logic is based heavily on the example in the Autoconf manual.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#ifndef PORTABLE_STDBOOL_H
#define PORTABLE_STDBOOL_H 1
+/*
+ * Allow inclusion of config.h to be skipped, since sometimes we have to use a
+ * stripped-down version of config.h with a different name.
+ */
+#ifndef CONFIG_H_INCLUDED
+# include <config.h>
+#endif
+
#if HAVE_STDBOOL_H
# include <stdbool.h>
#else
diff --git a/portable/strlcat.c b/portable/strlcat.c
index f696db3..3bee4ee 100644
--- a/portable/strlcat.c
+++ b/portable/strlcat.c
@@ -9,8 +9,18 @@
* space available in the destination buffer, not just the amount of space
* remaining.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/portable/strlcpy.c b/portable/strlcpy.c
index 596e968..df75fd8 100644
--- a/portable/strlcpy.c
+++ b/portable/strlcpy.c
@@ -8,8 +8,18 @@
* total space required is returned. The destination string is not nul-filled
* like strncpy does, just nul-terminated.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/portable/system.h b/portable/system.h
index 461601b..d1ccc94 100644
--- a/portable/system.h
+++ b/portable/system.h
@@ -13,13 +13,24 @@
* #include <stddef.h>
* #include <stdint.h>
* #include <string.h>
+ * #include <strings.h>
* #include <unistd.h>
*
* Missing functions are provided via #define or prototyped if available from
* the portable helper library. Also provides some standard #defines.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#ifndef PORTABLE_SYSTEM_H
@@ -38,6 +49,9 @@
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
@@ -56,6 +70,38 @@
/* Get the bool type. */
#include <portable/stdbool.h>
+/* Windows provides snprintf under a different name. */
+#ifdef _WIN32
+# define snprintf _snprintf
+#endif
+
+/* Windows does not define ssize_t. */
+#ifndef HAVE_SSIZE_T
+typedef ptrdiff_t ssize_t;
+#endif
+
+/*
+ * POSIX requires that these be defined in <unistd.h>. If one of them has
+ * been defined, all the rest almost certainly have.
+ */
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+#endif
+
+/*
+ * C99 requires va_copy. Older versions of GCC provide __va_copy. Per the
+ * Autoconf manual, memcpy is a generally portable fallback.
+ */
+#ifndef va_copy
+# ifdef __va_copy
+# define va_copy(d, s) __va_copy((d), (s))
+# else
+# define va_copy(d, s) memcpy(&(d), &(s), sizeof(va_list))
+# endif
+#endif
+
BEGIN_DECLS
/* Default to a hidden visibility for all portability functions. */
@@ -96,31 +142,4 @@ extern size_t strlcpy(char *, const char *, size_t);
END_DECLS
-/* Windows provides snprintf under a different name. */
-#ifdef _WIN32
-# define snprintf _snprintf
-#endif
-
-/*
- * POSIX requires that these be defined in <unistd.h>. If one of them has
- * been defined, all the rest almost certainly have.
- */
-#ifndef STDIN_FILENO
-# define STDIN_FILENO 0
-# define STDOUT_FILENO 1
-# define STDERR_FILENO 2
-#endif
-
-/*
- * C99 requires va_copy. Older versions of GCC provide __va_copy. Per the
- * Autoconf manual, memcpy is a generally portable fallback.
- */
-#ifndef va_copy
-# ifdef __va_copy
-# define va_copy(d, s) __va_copy((d), (s))
-# else
-# define va_copy(d, s) memcpy(&(d), &(s), sizeof(va_list))
-# endif
-#endif
-
#endif /* !PORTABLE_SYSTEM_H */
diff --git a/portable/uio.h b/portable/uio.h
index 3c9e840..3bd1f96 100644
--- a/portable/uio.h
+++ b/portable/uio.h
@@ -5,8 +5,18 @@
* (primarily Windows). Currently, the corresponding readv and writev
* functions are not provided or prototyped here.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#ifndef PORTABLE_UIO_H
diff --git a/tests/client/full-t.in b/tests/client/full-t.in
index ce2789d..680e78f 100644
--- a/tests/client/full-t.in
+++ b/tests/client/full-t.in
@@ -56,19 +56,19 @@ chdir "$ENV{SOURCE}" or die "Cannot chdir to $ENV{SOURCE}: $!\n";
SKIP: {
skip 'no keytab configuration', $total
- unless -f "$ENV{BUILD}/data/test.keytab";
+ unless -f "$ENV{BUILD}/config/keytab";
my $remctld = '@REMCTLD@';
skip 'remctld not found', $total unless $remctld;
# Spawn remctld and get local tickets. Don't destroy the user's Kerberos
# ticket cache.
unlink ('krb5cc_test', 'test-pid');
- my $principal = contents ("$ENV{BUILD}/data/test.principal");
+ my $principal = contents ("$ENV{BUILD}/config/principal");
remctld_spawn ($remctld, $principal,
- "$ENV{BUILD}/data/test.keytab",
+ "$ENV{BUILD}/config/keytab",
"$ENV{SOURCE}/data/full.conf");
$ENV{KRB5CCNAME} = 'krb5cc_test';
- getcreds ("$ENV{BUILD}/data/test.keytab", $principal);
+ getcreds ("$ENV{BUILD}/config/keytab", $principal);
# Use Wallet::Admin to set up the database.
db_setup;
diff --git a/tests/client/prompt-t.in b/tests/client/prompt-t.in
index 1d8b079..682cd70 100644
--- a/tests/client/prompt-t.in
+++ b/tests/client/prompt-t.in
@@ -21,11 +21,11 @@ chdir "$ENV{SOURCE}" or die "Cannot chdir to $ENV{SOURCE}: $!\n";
SKIP: {
skip 'no password configuration', $total
- unless -f "$ENV{BUILD}/data/test.password";
+ unless -f "$ENV{BUILD}/config/password";
my $remctld = '@REMCTLD@';
skip 'remctld not found', $total unless $remctld;
eval { require Expect };
- skip 'Exepct module not found', $total if $@;
+ skip 'Expect module not found', $total if $@;
# Disable sending of wallet's output to our standard output. Do this
# twice to avoid Perl warnings.
@@ -34,14 +34,14 @@ SKIP: {
# Spawn remctld and set up with a different ticket cache.
unlink ('krb5cc_test', 'test-pid');
- my $principal = contents ("$ENV{BUILD}/data/test.principal");
- remctld_spawn ($remctld, $principal, "$ENV{BUILD}/data/test.keytab",
+ my $principal = contents ("$ENV{BUILD}/config/principal");
+ remctld_spawn ($remctld, $principal, "$ENV{BUILD}/config/keytab",
"$ENV{SOURCE}/data/basic.conf");
$ENV{KRB5CCNAME} = 'krb5cc_test';
# Read in the principal and password.
- open (PASS, '<', "$ENV{BUILD}/data/test.password")
- or die "Cannot open $ENV{BUILD}/data/test.password: $!\n";
+ open (PASS, '<', "$ENV{BUILD}/config/password")
+ or die "Cannot open $ENV{BUILD}/config/password: $!\n";
my $user = <PASS>;
my $password = <PASS>;
close PASS;
diff --git a/tests/config/README b/tests/config/README
new file mode 100644
index 0000000..2992a11
--- /dev/null
+++ b/tests/config/README
@@ -0,0 +1,24 @@
+This directory contains configuration required to run the complete wallet
+test suite. If there is no configuration in this directory, some of the
+tests will be skipped. To enable the full test suite, create the
+following files:
+
+keytab
+
+ A valid Kerberos keytab for a principal, preferrably in your local
+ realm. This will be used to test network interactions that require
+ Kerberos authentication.
+
+principal
+
+ The name of the Kerberos principal whose keys are stored in keytab.
+
+password
+
+ This file should contain two lines. The first line is the
+ fully-qualified principal (including the realm) of a Kerberos
+ principal to use for testing authentication. The second line is
+ the password for that principal. The realm of the principal must
+ be configured in your system krb5.conf file or in DNS configuration
+ picked up by your Kerberos libraries and must be in the same realm as
+ the keytab above or have valid cross-realm trust to it.
diff --git a/tests/data/perl.conf b/tests/data/perl.conf
new file mode 100644
index 0000000..eaf7443
--- /dev/null
+++ b/tests/data/perl.conf
@@ -0,0 +1,6 @@
+# Configuration for Perl tests. -*- perl -*-
+
+# No special configuration yet.
+
+# File must end with this line.
+1;
diff --git a/tests/docs/pod-spelling-t b/tests/docs/pod-spelling-t
index eaa7dd6..e1a95cd 100755
--- a/tests/docs/pod-spelling-t
+++ b/tests/docs/pod-spelling-t
@@ -1,80 +1,52 @@
#!/usr/bin/perl
#
-# Check for spelling errors in POD documentation
+# Checks all POD files in the tree for spelling errors using Test::Spelling.
+# This test is disabled unless RRA_MAINTAINER_TESTS is set, since spelling
+# dictionaries vary too much between environments.
#
-# Checks all POD files in the tree for spelling problems using Pod::Spell and
-# either aspell or ispell. aspell is preferred. This test is disabled unless
-# RRA_MAINTAINER_TESTS is set, since spelling dictionaries vary too much
-# between environments.
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
#
-# Copyright 2008, 2009 Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2012, 2013
+# The Board of Trustees of the Leland Stanford Junior University
#
-# See LICENSE for licensing terms.
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+use 5.006;
use strict;
-use Test::More;
+use warnings;
-# Skip all spelling tests unless the maintainer environment variable is set.
-plan skip_all => 'spelling tests only run for maintainer'
- unless $ENV{RRA_MAINTAINER_TESTS};
+use lib "$ENV{SOURCE}/tap/perl";
+
+use Test::More;
+use Test::RRA qw(skip_unless_maintainer use_prereq);
+use Test::RRA::Automake qw(automake_setup perl_dirs);
-# Load required Perl modules.
-eval 'use Test::Pod 1.00';
-plan skip_all => 'Test::Pod 1.00 required for testing POD' if $@;
-eval 'use Pod::Spell';
-plan skip_all => 'Pod::Spell required to test POD spelling' if $@;
+# Only run this test for the maintainer.
+skip_unless_maintainer('Spelling tests');
-# Locate a spell-checker. hunspell is not currently supported due to its lack
-# of support for contractions (at least in the version in Debian).
-my @spell;
-my %options = (aspell => [ qw(-d en_US --home-dir=./ list) ],
- ispell => [ qw(-d american -l -p /dev/null) ]);
-SEARCH: for my $program (qw/aspell ispell/) {
- for my $dir (split ':', $ENV{PATH}) {
- if (-x "$dir/$program") {
- @spell = ("$dir/$program", @{ $options{$program} });
- }
- last SEARCH if @spell;
- }
-}
-plan skip_all => 'aspell or ispell required to test POD spelling'
- unless @spell;
+# Load prerequisite modules.
+use_prereq('Test::Spelling');
-# Prerequisites are satisfied, so we're going to do some testing. Figure out
-# what POD files we have and from that develop our plan.
-$| = 1;
-my @pod = map {
- my $pod = "$ENV{SOURCE}/../" . $_;
- $pod =~ s,[^/.][^/]*/../,,g;
- $pod;
-} qw(client/wallet.pod client/wallet-rekey.pod server/keytab-backend
- server/wallet-admin server/wallet-backend server/wallet-report);
-plan tests => scalar @pod;
+# Set up Automake testing.
+automake_setup();
-# Finally, do the checks.
-for my $pod (@pod) {
- my $child = open (CHILD, '-|');
- if (not defined $child) {
- BAIL_OUT ("cannot fork: $!");
- } elsif ($child == 0) {
- my $pid = open (SPELL, '|-', @spell)
- or BAIL_OUT ("cannot run @spell: $!");
- open (POD, '<', $pod) or BAIL_OUT ("cannot open $pod: $!");
- my $parser = Pod::Spell->new;
- $parser->parse_from_filehandle (\*POD, \*SPELL);
- close POD;
- close SPELL;
- exit ($? >> 8);
- } else {
- my @words = <CHILD>;
- close CHILD;
- SKIP: {
- skip "@spell failed for $pod", 1 unless $? == 0;
- for (@words) {
- s/^\s+//;
- s/\s+$//;
- }
- is ("@words", '', $pod);
- }
- }
-}
+# Run the tests.
+all_pod_files_spelling_ok(perl_dirs());
diff --git a/tests/docs/pod-t b/tests/docs/pod-t
index e25ade2..2743287 100755
--- a/tests/docs/pod-t
+++ b/tests/docs/pod-t
@@ -1,22 +1,48 @@
#!/usr/bin/perl -w
#
-# Test POD formatting for documentation.
+# Check all POD documents in the tree, except for any embedded Perl module
+# distribution, for POD formatting errors.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2008, 2010 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2012, 2013
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
#
-# See LICENSE for licensing terms.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+use 5.006;
use strict;
+use warnings;
+
+use lib "$ENV{SOURCE}/tap/perl";
+
use Test::More;
-eval 'use Test::Pod 1.00';
-plan skip_all => 'Test::Pod 1.00 required for testing POD' if $@;
+use Test::RRA qw(use_prereq);
+use Test::RRA::Automake qw(automake_setup perl_dirs);
+
+# Load prerequisite modules.
+use_prereq('Test::Pod');
+
+# Set up Automake testing.
+automake_setup();
-my @files = qw(client/wallet.pod client/wallet-rekey.pod server/keytab-backend
- server/wallet-admin server/wallet-backend
- server/wallet-report);
-my $total = scalar (@files);
-plan tests => $total;
-for my $file (@files) {
- pod_file_ok ("$ENV{SOURCE}/../$file", $file);
-}
+# Run the tests.
+all_pod_files_ok(perl_dirs());
diff --git a/tests/portable/asprintf-t.c b/tests/portable/asprintf-t.c
index 04fbd1b..4513a85 100644
--- a/tests/portable/asprintf-t.c
+++ b/tests/portable/asprintf-t.c
@@ -1,11 +1,18 @@
/*
* asprintf and vasprintf test suite.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2006, 2008, 2009
- * Board of Trustees, Leland Stanford Jr. University
*
- * See LICENSE for licensing terms.
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/tests/portable/mkstemp-t.c b/tests/portable/mkstemp-t.c
index 54701f7..98c708e 100644
--- a/tests/portable/mkstemp-t.c
+++ b/tests/portable/mkstemp-t.c
@@ -1,11 +1,18 @@
/*
* mkstemp test suite.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2002, 2004, 2008, 2009
- * Board of Trustees, Leland Stanford Jr. University
*
- * See LICENSE for licensing terms.
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/tests/portable/setenv-t.c b/tests/portable/setenv-t.c
index 5bc59ce..a1aecb5 100644
--- a/tests/portable/setenv-t.c
+++ b/tests/portable/setenv-t.c
@@ -1,14 +1,18 @@
/*
* setenv test suite.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2009 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/tests/portable/snprintf-t.c b/tests/portable/snprintf-t.c
index 4b64f5b..927de96 100644
--- a/tests/portable/snprintf-t.c
+++ b/tests/portable/snprintf-t.c
@@ -1,14 +1,20 @@
/*
* snprintf test suite.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ * Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010
+ * The Board of Trustees of the Leland Stanford Junior University
+ * Copyright 1995 Patrick Powell
+ * Copyright 2001 Hrvoje Niksic
*
- * See LICENSE for licensing terms.
+ * This code is based on code written by Patrick Powell (papowell@astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
*/
#include <config.h>
diff --git a/tests/portable/strlcat-t.c b/tests/portable/strlcat-t.c
index e02c277..54d0d40 100644
--- a/tests/portable/strlcat-t.c
+++ b/tests/portable/strlcat-t.c
@@ -1,14 +1,18 @@
/*
* strlcat test suite.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2009 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/tests/portable/strlcpy-t.c b/tests/portable/strlcpy-t.c
index ba224ba..26aa8f2 100644
--- a/tests/portable/strlcpy-t.c
+++ b/tests/portable/strlcpy-t.c
@@ -1,14 +1,18 @@
/*
* strlcpy test suite.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2009 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#include <config.h>
diff --git a/tests/runtests.c b/tests/runtests.c
index ab77629..4249875 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -3,14 +3,15 @@
*
* Usage:
*
- * runtests <test-list>
+ * runtests [-b <build-dir>] [-s <source-dir>] <test-list>
+ * runtests -o [-b <build-dir>] [-s <source-dir>] <test>
*
- * Expects a list of executables located in the given file, one line per
- * executable. For each one, runs it as part of a test suite, reporting
- * results. Test output should start with a line containing the number of
- * tests (numbered from 1 to this number), optionally preceded by "1..",
- * although that line may be given anywhere in the output. Each additional
- * line should be in the following format:
+ * In the first case, expects a list of executables located in the given file,
+ * one line per executable. For each one, runs it as part of a test suite,
+ * reporting results. Test output should start with a line containing the
+ * number of tests (numbered from 1 to this number), optionally preceded by
+ * "1..", although that line may be given anywhere in the output. Each
+ * additional line should be in the following format:
*
* ok <number>
* not ok <number>
@@ -39,10 +40,21 @@
* This is a subset of TAP as documented in Test::Harness::TAP or
* TAP::Parser::Grammar, which comes with Perl.
*
+ * If the -o option is given, instead run a single test and display all of its
+ * output. This is intended for use with failing tests so that the person
+ * running the test suite can get more details about what failed.
+ *
+ * If built with the C preprocessor symbols SOURCE and BUILD defined, C TAP
+ * Harness will export those values in the environment so that tests can find
+ * the source and build directory and will look for tests under both
+ * directories. These paths can also be set with the -b and -s command-line
+ * options, which will override anything set at build time.
+ *
* Any bug reports, bug fixes, and improvements are very much welcome and
- * should be sent to the e-mail address below.
+ * should be sent to the e-mail address below. This program is part of C TAP
+ * Harness <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
*
- * Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010
+ * Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011
* Russ Allbery <rra@stanford.edu>
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -64,6 +76,13 @@
* DEALINGS IN THE SOFTWARE.
*/
+/* Required for fdopen(), getopt(), and putenv(). */
+#if defined(__STRICT_ANSI__) || defined(PEDANTIC)
+# ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 500
+# endif
+#endif
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -71,6 +90,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -133,10 +153,10 @@ struct testset {
unsigned long skipped; /* Count of skipped tests (passed). */
unsigned long allocated; /* The size of the results table. */
enum test_status *results; /* Table of results by test number. */
- int aborted; /* Whether the set as aborted. */
+ unsigned int aborted; /* Whether the set as aborted. */
int reported; /* Whether the results were reported. */
int status; /* The exit status of the test. */
- int all_skipped; /* Whether all tests were skipped. */
+ unsigned int all_skipped; /* Whether all tests were skipped. */
char *reason; /* Why all tests were skipped. */
};
@@ -147,6 +167,23 @@ struct testlist {
};
/*
+ * Usage message. Should be used as a printf format with two arguments: the
+ * path to runtests, given twice.
+ */
+static const char usage_message[] = "\
+Usage: %s [-b <build-dir>] [-s <source-dir>] <test-list>\n\
+ %s -o [-b <build-dir>] [-s <source-dir>] <test>\n\
+\n\
+Options:\n\
+ -b <build-dir> Set the build directory to <build-dir>\n\
+ -o Run a single test rather than a list of tests\n\
+ -s <source-dir> Set the source directory to <source-dir>\n\
+\n\
+runtests normally runs each test listed in a file whose path is given as\n\
+its command-line argument. With the -o option, it instead runs a single\n\
+test and shows its complete output.\n";
+
+/*
* Header used for test output. %s is replaced by the file name of the list
* of tests.
*/
@@ -367,7 +404,9 @@ test_plan(const char *line, struct testset *ts)
* Get the count, check it for validity, and initialize the struct. If we
* have something of the form "1..0 # skip foo", the whole file was
* skipped; record that. If we do skip the whole file, zero out all of
- * our statistics, since they're no longer relevant.
+ * our statistics, since they're no longer relevant. strtol is called
+ * with a second argument to advance the line pointer past the count to
+ * make it simpler to detect the # skip case.
*/
n = strtol(line, (char **) &line, 10);
if (n == 0) {
@@ -437,6 +476,7 @@ test_checkline(const char *line, struct testset *ts)
char *end;
long number;
unsigned long i, current;
+ int outlen;
/* Before anything, check for a test abort. */
bail = strstr(line, "Bail out!");
@@ -557,7 +597,8 @@ test_checkline(const char *line, struct testset *ts)
ts->results[current - 1] = status;
test_backspace(ts);
if (isatty(STDOUT_FILENO)) {
- ts->length = printf("%lu/%lu", current, ts->count);
+ outlen = printf("%lu/%lu", current, ts->count);
+ ts->length = (outlen >= 0) ? outlen : 0;
fflush(stdout);
}
}
@@ -565,23 +606,20 @@ test_checkline(const char *line, struct testset *ts)
/*
* Print out a range of test numbers, returning the number of characters it
- * took up. Add a comma and a space before the range if chars indicates that
+ * took up. Takes the first number, the last number, the number of characters
+ * already printed on the line, and the limit of number of characters the line
+ * can hold. Add a comma and a space before the range if chars indicates that
* something has already been printed on the line, and print ... instead if
* chars plus the space needed would go over the limit (use a limit of 0 to
- * disable this.
+ * disable this).
*/
static unsigned int
test_print_range(unsigned long first, unsigned long last, unsigned int chars,
unsigned int limit)
{
unsigned int needed = 0;
- unsigned int out = 0;
unsigned long n;
- if (chars > 0) {
- needed += 2;
- if (!limit || chars <= limit) out += printf(", ");
- }
for (n = first; n > 0; n /= 10)
needed++;
if (last > first) {
@@ -589,15 +627,26 @@ test_print_range(unsigned long first, unsigned long last, unsigned int chars,
needed++;
needed++;
}
- if (limit && chars + needed > limit) {
- if (chars <= limit)
- out += printf("...");
+ if (chars > 0)
+ needed += 2;
+ if (limit > 0 && chars + needed > limit) {
+ needed = 0;
+ if (chars <= limit) {
+ if (chars > 0) {
+ printf(", ");
+ needed += 2;
+ }
+ printf("...");
+ needed += 3;
+ }
} else {
+ if (chars > 0)
+ printf(", ");
if (last > first)
- out += printf("%lu-", first);
- out += printf("%lu", last);
+ printf("%lu-", first);
+ printf("%lu", last);
}
- return out;
+ return needed;
}
@@ -825,14 +874,14 @@ test_fail_summary(const struct testlist *fails)
last = i + 1;
else {
if (first != 0)
- chars += test_print_range(first, last, chars, 20);
+ chars += test_print_range(first, last, chars, 19);
first = i + 1;
last = i + 1;
}
}
}
if (first != 0)
- test_print_range(first, last, chars, 20);
+ test_print_range(first, last, chars, 19);
putchar('\n');
free(ts->file);
free(ts->path);
@@ -861,10 +910,17 @@ find_test(const char *name, struct testset *ts, const char *source,
const char *build)
{
char *path;
- const char *bases[] = { ".", build, source, NULL };
+ const char *bases[4];
unsigned int i;
- for (i = 0; bases[i] != NULL; i++) {
+ bases[0] = ".";
+ bases[1] = build;
+ bases[2] = source;
+ bases[3] = NULL;
+
+ for (i = 0; i < 3; i++) {
+ if (bases[i] == NULL)
+ continue;
path = xmalloc(strlen(bases[i]) + strlen(name) + 4);
sprintf(path, "%s/%s-t", bases[i], name);
if (access(path, X_OK) != 0)
@@ -993,6 +1049,7 @@ test_batch(const char *testlist, const char *source, const char *build)
failed += ts.failed;
}
total -= skipped;
+ fclose(tests);
/* Stop the timer and get our child resource statistics. */
gettimeofday(&end, NULL);
@@ -1060,17 +1117,23 @@ int
main(int argc, char *argv[])
{
int option;
+ int status = 0;
int single = 0;
- char *setting;
+ char *source_env = NULL;
+ char *build_env = NULL;
const char *list;
const char *source = SOURCE;
const char *build = BUILD;
- while ((option = getopt(argc, argv, "b:os:")) != EOF) {
+ while ((option = getopt(argc, argv, "b:hos:")) != EOF) {
switch (option) {
case 'b':
build = optarg;
break;
+ case 'h':
+ printf(usage_message, argv[0], argv[0]);
+ exit(0);
+ break;
case 'o':
single = 1;
break;
@@ -1081,36 +1144,46 @@ main(int argc, char *argv[])
exit(1);
}
}
- argc -= optind;
- argv += optind;
- if (argc != 1) {
- fprintf(stderr, "Usage: runtests <test-list>\n");
+ if (argc - optind != 1) {
+ fprintf(stderr, usage_message, argv[0], argv[0]);
exit(1);
}
+ argc -= optind;
+ argv += optind;
if (source != NULL) {
- setting = xmalloc(strlen("SOURCE=") + strlen(source) + 1);
- sprintf(setting, "SOURCE=%s", source);
- if (putenv(setting) != 0)
+ source_env = xmalloc(strlen("SOURCE=") + strlen(source) + 1);
+ sprintf(source_env, "SOURCE=%s", source);
+ if (putenv(source_env) != 0)
sysdie("cannot set SOURCE in the environment");
}
if (build != NULL) {
- setting = xmalloc(strlen("BUILD=") + strlen(build) + 1);
- sprintf(setting, "BUILD=%s", build);
- if (putenv(setting) != 0)
+ build_env = xmalloc(strlen("BUILD=") + strlen(build) + 1);
+ sprintf(build_env, "BUILD=%s", build);
+ if (putenv(build_env) != 0)
sysdie("cannot set BUILD in the environment");
}
- if (single) {
+ if (single)
test_single(argv[0], source, build);
- exit(0);
- } else {
+ else {
list = strrchr(argv[0], '/');
if (list == NULL)
list = argv[0];
else
list++;
printf(banner, list);
- exit(test_batch(argv[0], source, build) ? 0 : 1);
+ status = test_batch(argv[0], source, build) ? 0 : 1;
+ }
+
+ /* For valgrind cleanliness. */
+ if (source_env != NULL) {
+ putenv((char *) "SOURCE=");
+ free(source_env);
+ }
+ if (build_env != NULL) {
+ putenv((char *) "BUILD=");
+ free(build_env);
}
+ exit(status);
}
diff --git a/tests/tap/basic.c b/tests/tap/basic.c
index 829f91a..e8196fc 100644
--- a/tests/tap/basic.c
+++ b/tests/tap/basic.c
@@ -1,22 +1,38 @@
/*
* Some utility routines for writing tests.
*
- * Herein are a variety of utility routines for writing tests. All routines
- * of the form ok() or is*() take a test number and some number of appropriate
- * arguments, check to be sure the results match the expected output using the
- * arguments, and print out something appropriate for that test number. Other
- * utility routines help in constructing more complex tests, skipping tests,
- * or setting up the TAP output format.
+ * Here are a variety of utility routines for writing tests compatible with
+ * the TAP protocol. All routines of the form ok() or is*() take a test
+ * number and some number of appropriate arguments, check to be sure the
+ * results match the expected output using the arguments, and print out
+ * something appropriate for that test number. Other utility routines help in
+ * constructing more complex tests, skipping tests, reporting errors, setting
+ * up the TAP output format, or finding things in the test environment.
*
- * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
- * Copyright 2006, 2007, 2008
- * Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * This file is part of C TAP Harness. The current version plus supporting
+ * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
*
- * See LICENSE for licensing terms.
+ * Copyright 2009, 2010, 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <errno.h>
@@ -24,12 +40,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef _WIN32
+# include <direct.h>
+#else
+# include <sys/stat.h>
+#endif
#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
#include <unistd.h>
-#include <tap/basic.h>
+#include <tests/tap/basic.h>
+
+/* Windows provides mkdir and rmdir under different names. */
+#ifdef _WIN32
+# define mkdir(p, m) _mkdir(p)
+# define rmdir(p) _rmdir(p)
+#endif
/*
* The test count. Always contains the number that will be used for the next
@@ -57,7 +82,9 @@ static int _lazy = 0;
/*
* Our exit handler. Called on completion of the test to report a summary of
- * results provided we're still in the original process.
+ * results provided we're still in the original process. This also handles
+ * printing out the plan if we used plan_lazy(), although that's suppressed if
+ * we never ran a test (due to an early bail, for example).
*/
static void
finish(void)
@@ -66,8 +93,9 @@ finish(void)
if (_planned == 0 && !_lazy)
return;
+ fflush(stderr);
if (_process != 0 && getpid() == _process) {
- if (_lazy) {
+ if (_lazy && highest > 0) {
printf("1..%lu\n", highest);
_planned = highest;
}
@@ -98,6 +126,7 @@ plan(unsigned long count)
if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
strerror(errno));
+ fflush(stderr);
printf("1..%lu\n", count);
testnum = 1;
_planned = count;
@@ -130,6 +159,7 @@ plan_lazy(void)
void
skip_all(const char *format, ...)
{
+ fflush(stderr);
printf("1..0 # skip");
if (format != NULL) {
va_list args;
@@ -162,6 +192,7 @@ print_desc(const char *format, va_list args)
void
ok(int success, const char *format, ...)
{
+ fflush(stderr);
printf("%sok %lu", success ? "" : "not ", testnum++);
if (!success)
_failed++;
@@ -182,6 +213,7 @@ ok(int success, const char *format, ...)
void
okv(int success, const char *format, va_list args)
{
+ fflush(stderr);
printf("%sok %lu", success ? "" : "not ", testnum++);
if (!success)
_failed++;
@@ -197,6 +229,7 @@ okv(int success, const char *format, va_list args)
void
skip(const char *reason, ...)
{
+ fflush(stderr);
printf("ok %lu # skip", testnum++);
if (reason != NULL) {
va_list args;
@@ -218,6 +251,7 @@ ok_block(unsigned long count, int status, const char *format, ...)
{
unsigned long i;
+ fflush(stderr);
for (i = 0; i < count; i++) {
printf("%sok %lu", status ? "" : "not ", testnum++);
if (!status)
@@ -242,6 +276,7 @@ skip_block(unsigned long count, const char *reason, ...)
{
unsigned long i;
+ fflush(stderr);
for (i = 0; i < count; i++) {
printf("ok %lu # skip", testnum++);
if (reason != NULL) {
@@ -264,6 +299,7 @@ skip_block(unsigned long count, const char *reason, ...)
void
is_int(long wanted, long seen, const char *format, ...)
{
+ fflush(stderr);
if (wanted == seen)
printf("ok %lu", testnum++);
else {
@@ -293,6 +329,7 @@ is_string(const char *wanted, const char *seen, const char *format, ...)
wanted = "(null)";
if (seen == NULL)
seen = "(null)";
+ fflush(stderr);
if (strcmp(wanted, seen) == 0)
printf("ok %lu", testnum++);
else {
@@ -312,37 +349,13 @@ is_string(const char *wanted, const char *seen, const char *format, ...)
/*
- * Takes an expected double and a seen double and assumes the test passes if
- * those two numbers match.
- */
-void
-is_double(double wanted, double seen, const char *format, ...)
-{
- if (wanted == seen)
- printf("ok %lu", testnum++);
- else {
- printf("# wanted: %g\n# seen: %g\n", wanted, seen);
- printf("not ok %lu", testnum++);
- _failed++;
- }
- if (format != NULL) {
- va_list args;
-
- va_start(args, format);
- print_desc(format, args);
- va_end(args);
- }
- putchar('\n');
-}
-
-
-/*
* Takes an expected unsigned long and a seen unsigned long and assumes the
* test passes if the two numbers match. Otherwise, reports them in hex.
*/
void
is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
{
+ fflush(stderr);
if (wanted == seen)
printf("ok %lu", testnum++);
else {
@@ -370,6 +383,7 @@ bail(const char *format, ...)
{
va_list args;
+ fflush(stderr);
fflush(stdout);
printf("Bail out! ");
va_start(args, format);
@@ -389,6 +403,7 @@ sysbail(const char *format, ...)
va_list args;
int oerrno = errno;
+ fflush(stderr);
fflush(stdout);
printf("Bail out! ");
va_start(args, format);
@@ -407,6 +422,7 @@ diag(const char *format, ...)
{
va_list args;
+ fflush(stderr);
fflush(stdout);
printf("# ");
va_start(args, format);
@@ -425,6 +441,7 @@ sysdiag(const char *format, ...)
va_list args;
int oerrno = errno;
+ fflush(stderr);
fflush(stdout);
printf("# ");
va_start(args, format);
@@ -435,6 +452,92 @@ sysdiag(const char *format, ...)
/*
+ * Allocate cleared memory, reporting a fatal error with bail on failure.
+ */
+void *
+bcalloc(size_t n, size_t size)
+{
+ void *p;
+
+ p = calloc(n, size);
+ if (p == NULL)
+ sysbail("failed to calloc %lu", (unsigned long)(n * size));
+ return p;
+}
+
+
+/*
+ * Allocate memory, reporting a fatal error with bail on failure.
+ */
+void *
+bmalloc(size_t size)
+{
+ void *p;
+
+ p = malloc(size);
+ if (p == NULL)
+ sysbail("failed to malloc %lu", (unsigned long) size);
+ return p;
+}
+
+
+/*
+ * Reallocate memory, reporting a fatal error with bail on failure.
+ */
+void *
+brealloc(void *p, size_t size)
+{
+ p = realloc(p, size);
+ if (p == NULL)
+ sysbail("failed to realloc %lu bytes", (unsigned long) size);
+ return p;
+}
+
+
+/*
+ * Copy a string, reporting a fatal error with bail on failure.
+ */
+char *
+bstrdup(const char *s)
+{
+ char *p;
+ size_t len;
+
+ len = strlen(s) + 1;
+ p = malloc(len);
+ if (p == NULL)
+ sysbail("failed to strdup %lu bytes", (unsigned long) len);
+ memcpy(p, s, len);
+ return p;
+}
+
+
+/*
+ * Copy up to n characters of a string, reporting a fatal error with bail on
+ * failure. Don't use the system strndup function, since it may not exist and
+ * the TAP library doesn't assume any portability support.
+ */
+char *
+bstrndup(const char *s, size_t n)
+{
+ const char *p;
+ char *copy;
+ size_t length;
+
+ /* Don't assume that the source string is nul-terminated. */
+ for (p = s; (size_t) (p - s) < n && *p != '\0'; p++)
+ ;
+ length = p - s;
+ copy = malloc(length + 1);
+ if (p == NULL)
+ sysbail("failed to strndup %lu bytes", (unsigned long) length);
+ memcpy(copy, s, length);
+ copy[length] = '\0';
+ return copy;
+}
+
+
+/*
* Locate a test file. Given the partial path to a file, look under BUILD and
* then SOURCE for the file and return the full path to the file. Returns
* NULL if the file doesn't exist. A non-NULL return should be freed with
@@ -458,9 +561,7 @@ test_file_path(const char *file)
if (base == NULL)
continue;
length = strlen(base) + 1 + strlen(file) + 1;
- path = malloc(length);
- if (path == NULL)
- sysbail("cannot allocate memory");
+ path = bmalloc(length);
sprintf(path, "%s/%s", base, file);
if (access(path, R_OK) == 0)
break;
@@ -482,3 +583,47 @@ test_file_path_free(char *path)
if (path != NULL)
free(path);
}
+
+
+/*
+ * Create a temporary directory, tmp, under BUILD if set and the current
+ * directory if it does not. Returns the path to the temporary directory in
+ * newly allocated memory, and calls bail on any failure. The return value
+ * should be freed with test_tmpdir_free.
+ *
+ * This function uses sprintf because it attempts to be independent of all
+ * other portability layers. The use immediately after a memory allocation
+ * should be safe without using snprintf or strlcpy/strlcat.
+ */
+char *
+test_tmpdir(void)
+{
+ const char *build;
+ char *path = NULL;
+ size_t length;
+
+ build = getenv("BUILD");
+ if (build == NULL)
+ build = ".";
+ length = strlen(build) + strlen("/tmp") + 1;
+ path = bmalloc(length);
+ sprintf(path, "%s/tmp", build);
+ if (access(path, X_OK) < 0)
+ if (mkdir(path, 0777) < 0)
+ sysbail("error creating temporary directory %s", path);
+ return path;
+}
+
+
+/*
+ * Free a path returned from test_tmpdir() and attempt to remove the
+ * directory. If we can't delete the directory, don't worry; something else
+ * that hasn't yet cleaned up may still be using it.
+ */
+void
+test_tmpdir_free(char *path)
+{
+ rmdir(path);
+ if (path != NULL)
+ free(path);
+}
diff --git a/tests/tap/basic.h b/tests/tap/basic.h
index 9602db4..fa4adaf 100644
--- a/tests/tap/basic.h
+++ b/tests/tap/basic.h
@@ -1,47 +1,38 @@
/*
* Basic utility routines for the TAP protocol.
*
- * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
- * Copyright 2006, 2007, 2008
- * Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * This file is part of C TAP Harness. The current version plus supporting
+ * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
*
- * See LICENSE for licensing terms.
+ * Copyright 2009, 2010, 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#ifndef TAP_BASIC_H
#define TAP_BASIC_H 1
+#include <tests/tap/macros.h>
#include <stdarg.h> /* va_list */
-#include <sys/types.h> /* pid_t */
-
-/*
- * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
- * could you use the __format__ form of the attributes, which is what we use
- * (to avoid confusion with other macros).
- */
-#ifndef __attribute__
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-# define __attribute__(spec) /* empty */
-# endif
-#endif
-
-/*
- * BEGIN_DECLS is used at the beginning of declarations so that C++
- * compilers don't mangle their names. END_DECLS is used at the end.
- */
-#undef BEGIN_DECLS
-#undef END_DECLS
-#ifdef __cplusplus
-# define BEGIN_DECLS extern "C" {
-# define END_DECLS }
-#else
-# define BEGIN_DECLS /* empty */
-# define END_DECLS /* empty */
-#endif
+#include <sys/types.h> /* size_t */
/*
* Used for iterating through arrays. ARRAY_SIZE returns the number of
@@ -93,8 +84,6 @@ void skip_block(unsigned long count, const char *reason, ...)
/* Check an expected value against a seen value. */
void is_int(long wanted, long seen, const char *format, ...)
__attribute__((__format__(printf, 3, 4)));
-void is_double(double wanted, double seen, const char *format, ...)
- __attribute__((__format__(printf, 3, 4)));
void is_string(const char *wanted, const char *seen, const char *format, ...)
__attribute__((__format__(printf, 3, 4)));
void is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
@@ -112,6 +101,18 @@ void diag(const char *format, ...)
void sysdiag(const char *format, ...)
__attribute__((__nonnull__, __format__(printf, 1, 2)));
+/* Allocate memory, reporting a fatal error with bail on failure. */
+void *bcalloc(size_t, size_t)
+ __attribute__((__alloc_size__(1, 2), __malloc__));
+void *bmalloc(size_t)
+ __attribute__((__alloc_size__(1), __malloc__));
+void *brealloc(void *, size_t)
+ __attribute__((__alloc_size__(2), __malloc__));
+char *bstrdup(const char *)
+ __attribute__((__malloc__, __nonnull__));
+char *bstrndup(const char *, size_t)
+ __attribute__((__malloc__, __nonnull__));
+
/*
* Find a test file under BUILD or SOURCE, returning the full path. The
* returned path should be freed with test_file_path_free().
@@ -120,6 +121,14 @@ char *test_file_path(const char *file)
__attribute__((__malloc__, __nonnull__));
void test_file_path_free(char *path);
+/*
+ * Create a temporary directory relative to BUILD and return the path. The
+ * returned path should be freed with test_tmpdir_free.
+ */
+char *test_tmpdir(void)
+ __attribute__((__malloc__));
+void test_tmpdir_free(char *path);
+
END_DECLS
#endif /* TAP_BASIC_H */
diff --git a/tests/tap/kerberos.c b/tests/tap/kerberos.c
index a17d980..474cf4f 100644
--- a/tests/tap/kerberos.c
+++ b/tests/tap/kerberos.c
@@ -1,47 +1,90 @@
/*
* Utility functions for tests that use Kerberos.
*
- * Currently only provides kerberos_setup(), which assumes a particular set of
- * data files in either the SOURCE or BUILD directories and, using those,
- * obtains Kerberos credentials, sets up a ticket cache, and sets the
- * environment variable pointing to the Kerberos keytab to use for testing.
+ * The core function is kerberos_setup, which loads Kerberos test
+ * configuration and returns a struct of information. It also supports
+ * obtaining initial tickets from the configured keytab and setting up
+ * KRB5CCNAME and KRB5_KTNAME if a Kerberos keytab is present. Also included
+ * are utility functions for setting up a krb5.conf file and reporting
+ * Kerberos errors or warnings during testing.
*
- * Copyright 2006, 2007, 2009, 2010
- * Board of Trustees, Leland Stanford Jr. University
+ * Some of the functionality here is only available if the Kerberos libraries
+ * are available.
*
- * See LICENSE for licensing terms.
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Copyright 2006, 2007, 2009, 2010, 2011, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
-#include <portable/krb5.h>
+#ifdef HAVE_KERBEROS
+# include <portable/krb5.h>
+#endif
#include <portable/system.h>
+#include <sys/stat.h>
+
#include <tests/tap/basic.h>
#include <tests/tap/kerberos.h>
-#include <util/concat.h>
-#include <util/xmalloc.h>
+#include <tests/tap/process.h>
+#include <tests/tap/string.h>
+
+/*
+ * Disable the requirement that format strings be literals, since it's easier
+ * to handle the possible patterns for kinit commands as an array.
+ */
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
/*
- * Obtain Kerberos tickets for the principal specified in test.principal using
- * the keytab specified in test.keytab, both of which are presumed to be in
- * tests/data in either the build or the source tree.
- *
- * Returns the contents of test.principal in newly allocated memory or NULL if
- * Kerberos tests are apparently not configured. If Kerberos tests are
- * configured but something else fails, calls bail().
+ * These variables hold the allocated configuration struct, the environment to
+ * point to a different Kerberos ticket cache, keytab, and configuration file,
+ * and the temporary directories used. We store them so that we can free them
+ * on exit for cleaner valgrind output, making it easier to find real memory
+ * leaks in the tested programs.
+ */
+static struct kerberos_config *config = NULL;
+static char *krb5ccname = NULL;
+static char *krb5_ktname = NULL;
+static char *krb5_config = NULL;
+static char *tmpdir_ticket = NULL;
+static char *tmpdir_conf = NULL;
+
+
+/*
+ * Obtain Kerberos tickets and fill in the principal config entry.
*
- * The error handling here is not great. We should have a bail_krb5 that uses
- * the same logic as messages-krb5.c, which hasn't yet been imported into
- * rra-c-util.
+ * There are two implementations of this function, one if we have native
+ * Kerberos libraries available and one if we don't. Uses keytab to obtain
+ * credentials, and fills in the cache member of the provided config struct.
*/
-char *
-kerberos_setup(void)
+#ifdef HAVE_KERBEROS
+
+static void
+kerberos_kinit(void)
{
- char *path, *krbtgt;
- const char *build, *realm;
- FILE *file;
- char principal[BUFSIZ];
+ char *name, *krbtgt;
krb5_error_code code;
krb5_context ctx;
krb5_ccache ccache;
@@ -49,89 +92,397 @@ kerberos_setup(void)
krb5_keytab keytab;
krb5_get_init_creds_opt *opts;
krb5_creds creds;
+ const char *realm;
- /* Read the principal name and find the keytab file. */
- path = test_file_path("data/test.principal");
- if (path == NULL)
- return NULL;
- file = fopen(path, "r");
- if (file == NULL) {
- free(path);
- return NULL;
- }
- if (fgets(principal, sizeof(principal), file) == NULL) {
- fclose(file);
- bail("cannot read %s", path);
- }
- fclose(file);
- if (principal[strlen(principal) - 1] != '\n')
- bail("no newline in %s", path);
- free(path);
- principal[strlen(principal) - 1] = '\0';
- path = test_file_path("data/test.keytab");
- if (path == NULL)
- return NULL;
-
- /* Set the KRB5CCNAME and KRB5_KTNAME environment variables. */
- build = getenv("BUILD");
- if (build == NULL)
- build = ".";
- putenv(concat("KRB5CCNAME=", build, "/data/test.cache", (char *) 0));
- putenv(concat("KRB5_KTNAME=", path, (char *) 0));
-
- /* Now do the Kerberos initialization. */
+ /*
+ * Determine the principal corresponding to that keytab. We copy the
+ * memory to ensure that it's allocated in the right memory domain on
+ * systems where that may matter (like Windows).
+ */
code = krb5_init_context(&ctx);
if (code != 0)
- bail("error initializing Kerberos");
+ bail_krb5(ctx, code, "error initializing Kerberos");
+ kprinc = kerberos_keytab_principal(ctx, config->keytab);
+ code = krb5_unparse_name(ctx, kprinc, &name);
+ if (code != 0)
+ bail_krb5(ctx, code, "error unparsing name");
+ krb5_free_principal(ctx, kprinc);
+ config->principal = bstrdup(name);
+ krb5_free_unparsed_name(ctx, name);
+
+ /* Now do the Kerberos initialization. */
code = krb5_cc_default(ctx, &ccache);
if (code != 0)
- bail("error setting ticket cache");
- code = krb5_parse_name(ctx, principal, &kprinc);
+ bail_krb5(ctx, code, "error setting ticket cache");
+ code = krb5_parse_name(ctx, config->principal, &kprinc);
if (code != 0)
- bail("error parsing principal %s", principal);
+ bail_krb5(ctx, code, "error parsing principal %s", config->principal);
realm = krb5_principal_get_realm(ctx, kprinc);
- krbtgt = concat("krbtgt/", realm, "@", realm, (char *) 0);
- code = krb5_kt_resolve(ctx, path, &keytab);
+ basprintf(&krbtgt, "krbtgt/%s@%s", realm, realm);
+ code = krb5_kt_resolve(ctx, config->keytab, &keytab);
if (code != 0)
- bail("cannot open keytab %s", path);
+ bail_krb5(ctx, code, "cannot open keytab %s", config->keytab);
code = krb5_get_init_creds_opt_alloc(ctx, &opts);
if (code != 0)
- bail("cannot allocate credential options");
+ bail_krb5(ctx, code, "cannot allocate credential options");
krb5_get_init_creds_opt_set_default_flags(ctx, NULL, realm, opts);
krb5_get_init_creds_opt_set_forwardable(opts, 0);
krb5_get_init_creds_opt_set_proxiable(opts, 0);
code = krb5_get_init_creds_keytab(ctx, &creds, kprinc, keytab, 0, krbtgt,
opts);
if (code != 0)
- bail("cannot get Kerberos tickets");
+ bail_krb5(ctx, code, "cannot get Kerberos tickets");
code = krb5_cc_initialize(ctx, ccache, kprinc);
if (code != 0)
- bail("error initializing ticket cache");
+ bail_krb5(ctx, code, "error initializing ticket cache");
code = krb5_cc_store_cred(ctx, ccache, &creds);
if (code != 0)
- bail("error storing credentials");
+ bail_krb5(ctx, code, "error storing credentials");
krb5_cc_close(ctx, ccache);
krb5_free_cred_contents(ctx, &creds);
krb5_kt_close(ctx, keytab);
krb5_free_principal(ctx, kprinc);
+ krb5_get_init_creds_opt_free(ctx, opts);
krb5_free_context(ctx);
free(krbtgt);
- free(path);
+}
- return xstrdup(principal);
+#else /* !HAVE_KERBEROS */
+
+static void
+kerberos_kinit(void)
+{
+ static const char * const format[] = {
+ "kinit --no-afslog -k -t %s %s >/dev/null 2>&1 </dev/null",
+ "kinit -k -t %s %s >/dev/null 2>&1 </dev/null",
+ "kinit -t %s %s >/dev/null 2>&1 </dev/null",
+ "kinit -k -K %s %s >/dev/null 2>&1 </dev/null"
+ };
+ FILE *file;
+ char *path;
+ char principal[BUFSIZ], *command;
+ size_t i;
+ int status;
+
+ /* Read the principal corresponding to the keytab. */
+ path = test_file_path("config/principal");
+ if (path == NULL) {
+ test_file_path_free(config->keytab);
+ config->keytab = NULL;
+ return;
+ }
+ file = fopen(path, "r");
+ if (file == NULL) {
+ test_file_path_free(path);
+ return;
+ }
+ test_file_path_free(path);
+ if (fgets(principal, sizeof(principal), file) == NULL)
+ bail("cannot read %s", path);
+ fclose(file);
+ if (principal[strlen(principal) - 1] != '\n')
+ bail("no newline in %s", path);
+ principal[strlen(principal) - 1] = '\0';
+ config->principal = bstrdup(principal);
+
+ /* Now do the Kerberos initialization. */
+ for (i = 0; i < ARRAY_SIZE(format); i++) {
+ basprintf(&command, format[i], config->keytab, principal);
+ status = system(command);
+ free(command);
+ if (status != -1 && WEXITSTATUS(status) == 0)
+ break;
+ }
+ if (status == -1 || WEXITSTATUS(status) != 0)
+ bail("cannot get Kerberos tickets");
}
+#endif /* !HAVE_KERBEROS */
+
/*
- * Clean up at the end of a test. Currently, all this does is remove the
- * ticket cache.
+ * Clean up at the end of a test. This removes the ticket cache and resets
+ * and frees the memory allocated for the environment variables so that
+ * valgrind output on test suites is cleaner.
*/
void
kerberos_cleanup(void)
{
char *path;
- path = concatpath(getenv("BUILD"), "data/test.cache");
- unlink(path);
- free(path);
+ if (tmpdir_ticket != NULL) {
+ basprintf(&path, "%s/krb5cc_test", tmpdir_ticket);
+ unlink(path);
+ free(path);
+ test_tmpdir_free(tmpdir_ticket);
+ tmpdir_ticket = NULL;
+ }
+ if (config != NULL) {
+ if (config->keytab != NULL) {
+ test_file_path_free(config->keytab);
+ free(config->principal);
+ free(config->cache);
+ }
+ if (config->userprinc != NULL) {
+ free(config->userprinc);
+ free(config->username);
+ free(config->password);
+ }
+ free(config);
+ config = NULL;
+ }
+ if (krb5ccname != NULL) {
+ putenv((char *) "KRB5CCNAME=");
+ free(krb5ccname);
+ krb5ccname = NULL;
+ }
+ if (krb5_ktname != NULL) {
+ putenv((char *) "KRB5_KTNAME=");
+ free(krb5_ktname);
+ krb5_ktname = NULL;
+ }
+}
+
+
+/*
+ * Obtain Kerberos tickets for the principal specified in config/principal
+ * using the keytab specified in config/keytab, both of which are presumed to
+ * be in tests in either the build or the source tree. Also sets KRB5_KTNAME
+ * and KRB5CCNAME.
+ *
+ * Returns the contents of config/principal in newly allocated memory or NULL
+ * if Kerberos tests are apparently not configured. If Kerberos tests are
+ * configured but something else fails, calls bail.
+ */
+struct kerberos_config *
+kerberos_setup(enum kerberos_needs needs)
+{
+ char *path;
+ char buffer[BUFSIZ];
+ FILE *file = NULL;
+
+ /* If we were called before, clean up after the previous run. */
+ if (config != NULL)
+ kerberos_cleanup();
+ config = bcalloc(1, sizeof(struct kerberos_config));
+
+ /*
+ * If we have a config/keytab file, set the KRB5CCNAME and KRB5_KTNAME
+ * environment variables and obtain initial tickets.
+ */
+ config->keytab = test_file_path("config/keytab");
+ if (config->keytab == NULL) {
+ if (needs == TAP_KRB_NEEDS_KEYTAB || needs == TAP_KRB_NEEDS_BOTH)
+ skip_all("Kerberos tests not configured");
+ } else {
+ tmpdir_ticket = test_tmpdir();
+ basprintf(&config->cache, "%s/krb5cc_test", tmpdir_ticket);
+ basprintf(&krb5ccname, "KRB5CCNAME=%s/krb5cc_test", tmpdir_ticket);
+ basprintf(&krb5_ktname, "KRB5_KTNAME=%s", config->keytab);
+ putenv(krb5ccname);
+ putenv(krb5_ktname);
+ kerberos_kinit();
+ }
+
+ /*
+ * If we have a config/password file, read it and fill out the relevant
+ * members of our config struct.
+ */
+ path = test_file_path("config/password");
+ if (path != NULL)
+ file = fopen(path, "r");
+ if (file == NULL) {
+ if (needs == TAP_KRB_NEEDS_PASSWORD || needs == TAP_KRB_NEEDS_BOTH)
+ skip_all("Kerberos tests not configured");
+ } else {
+ if (fgets(buffer, sizeof(buffer), file) == NULL)
+ bail("cannot read %s", path);
+ if (buffer[strlen(buffer) - 1] != '\n')
+ bail("no newline in %s", path);
+ buffer[strlen(buffer) - 1] = '\0';
+ config->userprinc = bstrdup(buffer);
+ if (fgets(buffer, sizeof(buffer), file) == NULL)
+ bail("cannot read password from %s", path);
+ fclose(file);
+ if (buffer[strlen(buffer) - 1] != '\n')
+ bail("password too long in %s", path);
+ buffer[strlen(buffer) - 1] = '\0';
+ config->password = bstrdup(buffer);
+
+ /*
+ * Strip the realm from the principal and set realm and username.
+ * This is not strictly correct; it doesn't cope with escaped @-signs
+ * or enterprise names.
+ */
+ config->username = bstrdup(config->userprinc);
+ config->realm = strchr(config->username, '@');
+ if (config->realm == NULL)
+ bail("test principal has no realm");
+ *config->realm = '\0';
+ config->realm++;
+ }
+ if (path != NULL)
+ test_file_path_free(path);
+
+ /*
+ * Register the cleanup function as an atexit handler so that the caller
+ * doesn't have to worry about cleanup.
+ */
+ if (atexit(kerberos_cleanup) != 0)
+ sysdiag("cannot register cleanup function");
+
+ /* Return the configuration. */
+ return config;
+}
+
+
+/*
+ * Clean up the krb5.conf file generated by kerberos_generate_conf and free
+ * the memory used to set the environment variable. This doesn't fail if the
+ * file and variable are already gone, allowing it to be harmlessly run
+ * multiple times.
+ *
+ * Normally called via an atexit handler.
+ */
+void
+kerberos_cleanup_conf(void)
+{
+ char *path;
+
+ if (tmpdir_conf != NULL) {
+ basprintf(&path, "%s/krb5.conf", tmpdir_conf);
+ unlink(path);
+ free(path);
+ test_tmpdir_free(tmpdir_conf);
+ tmpdir_conf = NULL;
+ }
+ putenv((char *) "KRB5_CONFIG=");
+ if (krb5_config != NULL) {
+ free(krb5_config);
+ krb5_config = NULL;
+ }
}
+
+
+/*
+ * Generate a krb5.conf file for testing and set KRB5_CONFIG to point to it.
+ * The [appdefaults] section will be stripped out and the default realm will
+ * be set to the realm specified, if not NULL. This will use config/krb5.conf
+ * in preference, so users can configure the tests by creating that file if
+ * the system file isn't suitable.
+ *
+ * Depends on data/generate-krb5-conf being present in the test suite.
+ */
+void
+kerberos_generate_conf(const char *realm)
+{
+ char *path;
+ const char *argv[3];
+
+ if (tmpdir_conf != NULL)
+ kerberos_cleanup_conf();
+ path = test_file_path("data/generate-krb5-conf");
+ if (path == NULL)
+ bail("cannot find generate-krb5-conf");
+ argv[0] = path;
+ argv[1] = realm;
+ argv[2] = NULL;
+ run_setup(argv);
+ test_file_path_free(path);
+ tmpdir_conf = test_tmpdir();
+ basprintf(&krb5_config, "KRB5_CONFIG=%s/krb5.conf", tmpdir_conf);
+ putenv(krb5_config);
+ if (atexit(kerberos_cleanup_conf) != 0)
+ sysdiag("cannot register cleanup function");
+}
+
+
+/*
+ * The remaining functions in this file are only available if Kerberos
+ * libraries are available.
+ */
+#ifdef HAVE_KERBEROS
+
+
+/*
+ * Report a Kerberos error and bail out.
+ */
+void
+bail_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
+{
+ const char *k5_msg = NULL;
+ char *message;
+ va_list args;
+
+ if (ctx != NULL)
+ k5_msg = krb5_get_error_message(ctx, code);
+ va_start(args, format);
+ bvasprintf(&message, format, args);
+ va_end(args);
+ if (k5_msg == NULL)
+ bail("%s", message);
+ else
+ bail("%s: %s", message, k5_msg);
+}
+
+
+/*
+ * Report a Kerberos error as a diagnostic to stderr.
+ */
+void
+diag_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
+{
+ const char *k5_msg = NULL;
+ char *message;
+ va_list args;
+
+ if (ctx != NULL)
+ k5_msg = krb5_get_error_message(ctx, code);
+ va_start(args, format);
+ bvasprintf(&message, format, args);
+ va_end(args);
+ if (k5_msg == NULL)
+ diag("%s", message);
+ else
+ diag("%s: %s", message, k5_msg);
+ free(message);
+ if (k5_msg != NULL)
+ krb5_free_error_message(ctx, k5_msg);
+}
+
+
+/*
+ * Find the principal of the first entry of a keytab and return it. The
+ * caller is responsible for freeing the result with krb5_free_principal.
+ * Exit on error.
+ */
+krb5_principal
+kerberos_keytab_principal(krb5_context ctx, const char *path)
+{
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+ krb5_principal princ;
+ krb5_error_code status;
+
+ status = krb5_kt_resolve(ctx, path, &keytab);
+ if (status != 0)
+ bail_krb5(ctx, status, "error opening %s", path);
+ status = krb5_kt_start_seq_get(ctx, keytab, &cursor);
+ if (status != 0)
+ bail_krb5(ctx, status, "error reading %s", path);
+ status = krb5_kt_next_entry(ctx, keytab, &entry, &cursor);
+ if (status == 0) {
+ status = krb5_copy_principal(ctx, entry.principal, &princ);
+ if (status != 0)
+ bail_krb5(ctx, status, "error copying principal from %s", path);
+ krb5_kt_free_entry(ctx, &entry);
+ }
+ if (status != 0)
+ bail("no principal found in keytab file %s", path);
+ krb5_kt_end_seq_get(ctx, keytab, &cursor);
+ krb5_kt_close(ctx, keytab);
+ return princ;
+}
+
+#endif /* HAVE_KERBEROS */
diff --git a/tests/tap/kerberos.h b/tests/tap/kerberos.h
index 1c64f70..31b6343 100644
--- a/tests/tap/kerberos.h
+++ b/tests/tap/kerberos.h
@@ -1,32 +1,125 @@
/*
* Utility functions for tests that use Kerberos.
*
- * Copyright 2006, 2007, 2009
- * Board of Trustees, Leland Stanford Jr. University
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * See LICENSE for licensing terms.
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Copyright 2006, 2007, 2009, 2011, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#ifndef TAP_KERBEROS_H
#define TAP_KERBEROS_H 1
#include <config.h>
-#include <portable/macros.h>
+#include <tests/tap/macros.h>
+
+#ifdef HAVE_KERBEROS
+# include <portable/krb5.h>
+#endif
+
+/* Holds the information parsed from the Kerberos test configuration. */
+struct kerberos_config {
+ char *keytab; /* Path to the keytab. */
+ char *principal; /* Principal whose keys are in the keytab. */
+ char *cache; /* Path to the Kerberos ticket cache. */
+ char *userprinc; /* The fully-qualified principal. */
+ char *username; /* The local (non-realm) part of principal. */
+ char *realm; /* The realm part of the principal. */
+ char *password; /* The password. */
+};
+
+/*
+ * Whether to skip all tests (by calling skip_all) in kerberos_setup if
+ * certain configuration information isn't available.
+ */
+enum kerberos_needs {
+ TAP_KRB_NEEDS_NONE,
+ TAP_KRB_NEEDS_KEYTAB,
+ TAP_KRB_NEEDS_PASSWORD,
+ TAP_KRB_NEEDS_BOTH
+};
BEGIN_DECLS
/*
- * Set up Kerberos, returning the test principal in newly allocated memory if
- * we were successful. If there is no principal in tests/data/test.principal
- * or no keytab in tests/data/test.keytab, return NULL. Otherwise, on
- * failure, calls bail().
+ * Set up Kerberos, returning the test configuration information. This
+ * obtains Kerberos tickets from config/keytab, if one is present, and stores
+ * them in a Kerberos ticket cache, sets KRB5_KTNAME and KRB5CCNAME. It also
+ * loads the principal and password from config/password, if it exists, and
+ * stores the principal, password, username, and realm in the returned struct.
+ *
+ * If there is no config/keytab file, KRB5_KTNAME and KRB5CCNAME won't be set
+ * and the keytab field will be NULL. If there is no config/password file,
+ * the principal field will be NULL. If the files exist but loading them
+ * fails, or authentication fails, kerberos_setup calls bail.
+ *
+ * kerberos_cleanup will be set up to run from an atexit handler. This means
+ * that any child processes that should not remove the Kerberos ticket cache
+ * should call _exit instead of exit. The principal will be automatically
+ * freed when kerberos_cleanup is called or if kerberos_setup is called again.
+ * The caller doesn't need to worry about it.
*/
-char *kerberos_setup(void)
+struct kerberos_config *kerberos_setup(enum kerberos_needs)
__attribute__((__malloc__));
-
-/* Clean up at the end of a test. */
void kerberos_cleanup(void);
+/*
+ * Generate a krb5.conf file for testing and set KRB5_CONFIG to point to it.
+ * The [appdefaults] section will be stripped out and the default realm will
+ * be set to the realm specified, if not NULL. This will use config/krb5.conf
+ * in preference, so users can configure the tests by creating that file if
+ * the system file isn't suitable.
+ *
+ * Depends on data/generate-krb5-conf being present in the test suite.
+ *
+ * kerberos_cleanup_conf will clean up after this function, but usually
+ * doesn't need to be called directly since it's registered as an atexit
+ * handler.
+ */
+void kerberos_generate_conf(const char *realm);
+void kerberos_cleanup_conf(void);
+
+/* Thes interfaces are only available with native Kerberos support. */
+#ifdef HAVE_KERBEROS
+
+/* Bail out with an error, appending the Kerberos error message. */
+void bail_krb5(krb5_context, krb5_error_code, const char *format, ...)
+ __attribute__((__noreturn__, __nonnull__, __format__(printf, 3, 4)));
+
+/* Report a diagnostic with Kerberos error to stderr prefixed with #. */
+void diag_krb5(krb5_context, krb5_error_code, const char *format, ...)
+ __attribute__((__nonnull__, __format__(printf, 3, 4)));
+
+/*
+ * Given a Kerberos context and the path to a keytab, retrieve the principal
+ * for the first entry in the keytab and return it. Calls bail on failure.
+ * The returned principal should be freed with krb5_free_principal.
+ */
+krb5_principal kerberos_keytab_principal(krb5_context, const char *path)
+ __attribute__((__nonnull__));
+
+#endif /* HAVE_KERBEROS */
+
END_DECLS
#endif /* !TAP_MESSAGES_H */
diff --git a/tests/tap/kerberos.sh b/tests/tap/kerberos.sh
index 904cae5..d2f174d 100644
--- a/tests/tap/kerberos.sh
+++ b/tests/tap/kerberos.sh
@@ -1,30 +1,61 @@
# Shell function library to initialize Kerberos credentials
#
+# Note that while many of the functions in this library could benefit from
+# using "local" to avoid possibly hammering global variables, Solaris /bin/sh
+# doesn't support local and this library aspires to be portable to Solaris
+# Bourne shell. Instead, all private variables are prefixed with "tap_".
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2009, 2010, 2011, 2012
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# See LICENSE for licensing terms.
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+# We use test_tmpdir.
+. "${SOURCE}/tap/libtap.sh"
# Set up Kerberos, including the ticket cache environment variable. Bail out
# if not successful, return 0 if successful, and return 1 if Kerberos is not
# configured. Sets the global principal variable to the principal to use.
kerberos_setup () {
- local keytab
- keytab=`test_file_path data/test.keytab`
- principal=`test_file_path data/test.principal`
+ tap_keytab=`test_file_path config/keytab`
+ principal=`test_file_path config/principal`
principal=`cat "$principal" 2>/dev/null`
- if [ -z "$keytab" ] || [ -z "$principal" ] ; then
+ if [ -z "$tap_keytab" ] || [ -z "$principal" ] ; then
return 1
fi
- KRB5CCNAME="$BUILD/data/test.cache"; export KRB5CCNAME
- kinit -k -t "$keytab" "$principal" >/dev/null </dev/null
+ KRB5CCNAME=`test_tmpdir`/krb5cc_test; export KRB5CCNAME
+ kinit --no-afslog -k -t "$tap_keytab" "$principal" >/dev/null </dev/null
status=$?
if [ $status != 0 ] ; then
- kinit -t "$keytab" "$principal" >/dev/null </dev/null
+ kinit -k -t "$tap_keytab" "$principal" >/dev/null </dev/null
+ status=$?
+ fi
+ if [ $status != 0 ] ; then
+ kinit -t "$tap_keytab" "$principal" >/dev/null </dev/null
status=$?
fi
if [ $status != 0 ] ; then
- kinit -k -K "$keytab" "$principal" >/dev/null </dev/null
+ kinit -k -K "$tap_keytab" "$principal" >/dev/null </dev/null
status=$?
fi
if [ $status != 0 ] ; then
@@ -35,7 +66,8 @@ kerberos_setup () {
# Clean up at the end of a test. Currently only removes the ticket cache.
kerberos_cleanup () {
- rm -f "$BUILD/data/test.cache"
+ tap_tmp=`test_tmpdir`
+ rm -f "$tap_tmp"/krb5cc_test
}
# List the contents of a keytab with enctypes and keys. This adjusts for the
@@ -44,11 +76,13 @@ kerberos_cleanup () {
# may just hang. Takes the keytab to list and the file into which to save the
# output, and strips off the header containing the file name.
ktutil_list () {
- if klist -keK "$1" > ktutil-tmp 2>/dev/null ; then
+ tap_tmp=`test_tmpdir`
+ if klist -keK "$1" > "$tap_tmp"/ktutil-tmp 2>/dev/null ; then
:
else
- ktutil -k "$1" list --keys > ktutil-tmp < /dev/null 2>/dev/null
+ ktutil -k "$1" list --keys > "$tap_tmp"/ktutil-tmp </dev/null \
+ 2>/dev/null
fi
- sed -e '/Keytab name:/d' -e "/^[^ ]*:/d" ktutil-tmp > "$2"
- rm -f ktutil-tmp
+ sed -e '/Keytab name:/d' -e "/^[^ ]*:/d" "$tap_tmp"/ktutil-tmp > "$2"
+ rm -f "$tap_tmp"/ktutil-tmp
}
diff --git a/tests/tap/libtap.sh b/tests/tap/libtap.sh
index a9b46d4..f9347d8 100644
--- a/tests/tap/libtap.sh
+++ b/tests/tap/libtap.sh
@@ -1,10 +1,36 @@
# Shell function library for test cases.
#
+# Note that while many of the functions in this library could benefit from
+# using "local" to avoid possibly hammering global variables, Solaris /bin/sh
+# doesn't support local and this library aspires to be portable to Solaris
+# Bourne shell. Instead, all private variables are prefixed with "tap_".
+#
+# This file provides a TAP-compatible shell function library useful for
+# writing test cases. It is part of C TAP Harness, which can be found at
+# <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
-# Copyright 2006, 2007, 2008 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2009, 2010, 2011, 2012 Russ Allbery <rra@stanford.edu>
+# Copyright 2006, 2007, 2008
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# See LICENSE for licensing terms.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
# Print out the number of test cases we expect to run.
plan () {
@@ -25,33 +51,35 @@ plan_lazy () {
# Report the test status on exit.
finish () {
- local highest looks
- highest=`expr "$count" - 1`
+ tap_highest=`expr "$count" - 1`
if [ "$planned" = 0 ] ; then
- echo "1..$highest"
- planned="$highest"
+ echo "1..$tap_highest"
+ planned="$tap_highest"
fi
- looks='# Looks like you'
+ tap_looks='# Looks like you'
if [ "$planned" -gt 0 ] ; then
- if [ "$planned" -gt "$highest" ] ; then
+ if [ "$planned" -gt "$tap_highest" ] ; then
if [ "$planned" -gt 1 ] ; then
- echo "$looks planned $planned tests but only ran $highest"
+ echo "$tap_looks planned $planned tests but only ran" \
+ "$tap_highest"
else
- echo "$looks planned $planned test but only ran $highest"
+ echo "$tap_looks planned $planned test but only ran" \
+ "$tap_highest"
fi
- elif [ "$planned" -lt "$highest" ] ; then
- local extra
- extra=`expr "$highest" - "$planned"`
+ elif [ "$planned" -lt "$tap_highest" ] ; then
+ tap_extra=`expr "$tap_highest" - "$planned"`
if [ "$planned" -gt 1 ] ; then
- echo "$looks planned $planned tests but ran $extra extra"
+ echo "$tap_looks planned $planned tests but ran" \
+ "$tap_extra extra"
else
- echo "$looks planned $planned test but ran $extra extra"
+ echo "$tap_looks planned $planned test but ran" \
+ "$tap_extra extra"
fi
elif [ "$failed" -gt 0 ] ; then
if [ "$failed" -gt 1 ] ; then
- echo "$looks failed $failed tests of $planned"
+ echo "$tap_looks failed $failed tests of $planned"
else
- echo "$looks failed $failed test of $planned"
+ echo "$tap_looks failed $failed test of $planned"
fi
elif [ "$planned" -gt 1 ] ; then
echo "# All $planned tests successful or skipped"
@@ -63,10 +91,9 @@ finish () {
# Skip the entire test suite. Should be run instead of plan.
skip_all () {
- local desc
- desc="$1"
- if [ -n "$desc" ] ; then
- echo "1..0 # skip $desc"
+ tap_desc="$1"
+ if [ -n "$tap_desc" ] ; then
+ echo "1..0 # skip $tap_desc"
else
echo "1..0 # skip"
fi
@@ -77,16 +104,15 @@ skip_all () {
# command is successful, false otherwise. The count starts at 1 and is
# updated each time ok is printed.
ok () {
- local desc
- desc="$1"
- if [ -n "$desc" ] ; then
- desc=" - $desc"
+ tap_desc="$1"
+ if [ -n "$tap_desc" ] ; then
+ tap_desc=" - $tap_desc"
fi
shift
if "$@" ; then
- echo ok $count$desc
+ echo ok "$count$tap_desc"
else
- echo not ok $count$desc
+ echo not ok "$count$tap_desc"
failed=`expr $failed + 1`
fi
count=`expr $count + 1`
@@ -101,58 +127,80 @@ skip () {
# Report the same status on a whole set of tests. Takes the count of tests,
# the description, and then the command to run to determine the status.
ok_block () {
- local end i desc
- i=$count
- end=`expr $count + $1`
- shift
- desc="$1"
+ tap_i=$count
+ tap_end=`expr $count + $1`
shift
- while [ "$i" -lt "$end" ] ; do
- ok "$desc" "$@"
- i=`expr $i + 1`
+ while [ "$tap_i" -lt "$tap_end" ] ; do
+ ok "$@"
+ tap_i=`expr $tap_i + 1`
done
}
# Skip a whole set of tests. Takes the count and then the reason for skipping
# the test.
skip_block () {
- local i end
- i=$count
- end=`expr $count + $1`
+ tap_i=$count
+ tap_end=`expr $count + $1`
shift
- while [ "$i" -lt "$end" ] ; do
+ while [ "$tap_i" -lt "$tap_end" ] ; do
skip "$@"
- i=`expr $i + 1`
+ tap_i=`expr $tap_i + 1`
done
}
+# Portable variant of printf '%s\n' "$*". In the majority of cases, this
+# function is slower than printf, because the latter is often implemented
+# as a builtin command. The value of the variable IFS is ignored.
+#
+# This macro must not be called via backticks inside double quotes, since this
+# will result in bizarre escaping behavior and lots of extra backslashes on
+# Solaris.
+puts () {
+ cat << EOH
+$@
+EOH
+}
+
# Run a program expected to succeed, and print ok if it does and produces the
# correct output. Takes the description, expected exit status, the expected
-# output, the command to run, and then any arguments for that command. Strip
-# a colon and everything after it off the output if the expected status is
-# non-zero, since this is probably a system-specific error message.
+# output, the command to run, and then any arguments for that command.
+# Standard output and standard error are combined when analyzing the output of
+# the command.
+#
+# If the command may contain system-specific error messages in its output,
+# add strip_colon_error before the command to post-process its output.
ok_program () {
- local desc w_status w_output output status
- desc="$1"
+ tap_desc="$1"
shift
- w_status="$1"
+ tap_w_status="$1"
shift
- w_output="$1"
+ tap_w_output="$1"
shift
- output=`"$@" 2>&1`
- status=$?
- if [ "$w_status" -ne 0 ] ; then
- output=`echo "$output" | sed 's/^\([^:]* [^:]*\):.*/\1/'`
- fi
- if [ $status = $w_status ] && [ x"$output" = x"$w_output" ] ; then
- ok "$desc" true
+ tap_output=`"$@" 2>&1`
+ tap_status=$?
+ if [ $tap_status = $tap_w_status ] \
+ && [ x"$tap_output" = x"$tap_w_output" ] ; then
+ ok "$tap_desc" true
else
- echo "# saw: ($status) $output"
- echo "# not: ($w_status) $w_output"
- ok "$desc" false
+ echo "# saw: ($tap_status) $tap_output"
+ echo "# not: ($tap_w_status) $tap_w_output"
+ ok "$tap_desc" false
fi
}
+# Strip a colon and everything after it off the output of a command, as long
+# as that colon comes after at least one whitespace character. (This is done
+# to avoid stripping the name of the program from the start of an error
+# message.) This is used to remove system-specific error messages (coming
+# from strerror, for example).
+strip_colon_error() {
+ tap_output=`"$@" 2>&1`
+ tap_status=$?
+ tap_output=`puts "$tap_output" | sed 's/^\([^ ]* [^:]*\):.*/\1/'`
+ puts "$tap_output"
+ return $tap_status
+}
+
# Bail out with an error message.
bail () {
echo 'Bail out!' "$@"
@@ -167,12 +215,32 @@ diag () {
# Search for the given file first in $BUILD and then in $SOURCE and echo the
# path where the file was found, or the empty string if the file wasn't
# found.
+#
+# This macro uses puts, so don't run it using backticks inside double quotes
+# or bizarre quoting behavior will happen with Solaris sh.
test_file_path () {
- if [ -f "$BUILD/$1" ] ; then
- echo "$BUILD/$1"
- elif [ -f "$SOURCE/$1" ] ; then
- echo "$SOURCE/$1"
+ if [ -n "$BUILD" ] && [ -f "$BUILD/$1" ] ; then
+ puts "$BUILD/$1"
+ elif [ -n "$SOURCE" ] && [ -f "$SOURCE/$1" ] ; then
+ puts "$SOURCE/$1"
else
echo ''
fi
}
+
+# Create $BUILD/tmp for use by tests for storing temporary files and return
+# the path (via standard output).
+#
+# This macro uses puts, so don't run it using backticks inside double quotes
+# or bizarre quoting behavior will happen with Solaris sh.
+test_tmpdir () {
+ if [ -z "$BUILD" ] ; then
+ tap_tmpdir="./tmp"
+ else
+ tap_tmpdir="$BUILD"/tmp
+ fi
+ if [ ! -d "$tap_tmpdir" ] ; then
+ mkdir "$tap_tmpdir" || bail "Error creating $tap_tmpdir"
+ fi
+ puts "$tap_tmpdir"
+}
diff --git a/tests/tap/macros.h b/tests/tap/macros.h
new file mode 100644
index 0000000..33fee42
--- /dev/null
+++ b/tests/tap/macros.h
@@ -0,0 +1,88 @@
+/*
+ * Helpful macros for TAP header files.
+ *
+ * This is not, strictly speaking, related to TAP, but any TAP add-on is
+ * probably going to need these macros, so define them in one place so that
+ * everyone can pull them in.
+ *
+ * This file is part of C TAP Harness. The current version plus supporting
+ * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+ *
+ * Copyright 2008, 2012 Russ Allbery <rra@stanford.edu>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TAP_MACROS_H
+#define TAP_MACROS_H 1
+
+/*
+ * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
+ * could you use the __format__ form of the attributes, which is what we use
+ * (to avoid confusion with other macros), and only with gcc 2.96 can you use
+ * the attribute __malloc__. 2.96 is very old, so don't bother trying to get
+ * the other attributes to work with GCC versions between 2.7 and 2.96.
+ */
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+# define __attribute__(spec) /* empty */
+# endif
+#endif
+
+/*
+ * We use __alloc_size__, but it was only available in fairly recent versions
+ * of GCC. Suppress warnings about the unknown attribute if GCC is too old.
+ * We know that we're GCC at this point, so we can use the GCC variadic macro
+ * extension, which will still work with versions of GCC too old to have C99
+ * variadic macro support.
+ */
+#if !defined(__attribute__) && !defined(__alloc_size__)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
+# define __alloc_size__(spec, args...) /* empty */
+# endif
+#endif
+
+/*
+ * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
+ * settings that GCC does. For them, suppress warnings about unknown
+ * attributes on declarations. This unfortunately will affect the entire
+ * compilation context, but there's no push and pop available.
+ */
+#if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__))
+# pragma GCC diagnostic ignored "-Wattributes"
+#endif
+
+/* Used for unused parameters to silence gcc warnings. */
+#define UNUSED __attribute__((__unused__))
+
+/*
+ * BEGIN_DECLS is used at the beginning of declarations so that C++
+ * compilers don't mangle their names. END_DECLS is used at the end.
+ */
+#undef BEGIN_DECLS
+#undef END_DECLS
+#ifdef __cplusplus
+# define BEGIN_DECLS extern "C" {
+# define END_DECLS }
+#else
+# define BEGIN_DECLS /* empty */
+# define END_DECLS /* empty */
+#endif
+
+#endif /* TAP_MACROS_H */
diff --git a/tests/tap/messages.c b/tests/tap/messages.c
index 3bb9a1a..abc2c49 100644
--- a/tests/tap/messages.c
+++ b/tests/tap/messages.c
@@ -5,24 +5,39 @@
* into a buffer that can be inspected later, allowing testing of error
* handling.
*
- * Copyright 2006, 2007, 2009
- * Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * See LICENSE for licensing terms.
+ * Copyright 2002, 2004, 2005 Russ Allbery <rra@stanford.edu>
+ * Copyright 2006, 2007, 2009, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
#include <portable/system.h>
+#include <tests/tap/macros.h>
#include <tests/tap/messages.h>
-#include <util/concat.h>
-#include <util/macros.h>
+#include <tests/tap/string.h>
#include <util/messages.h>
-#include <util/xmalloc.h>
/* A global buffer into which message_log_buffer stores error messages. */
char *errors = NULL;
@@ -33,18 +48,18 @@ char *errors = NULL;
* error_capture.
*/
static void
-message_log_buffer(int len, const char *fmt, va_list args, int error UNUSED)
+message_log_buffer(int len UNUSED, const char *fmt, va_list args,
+ int error UNUSED)
{
char *message;
- message = xmalloc(len + 1);
- vsnprintf(message, len + 1, fmt, args);
- if (errors == NULL) {
- errors = concat(message, "\n", (char *) 0);
- } else {
+ bvasprintf(&message, fmt, args);
+ if (errors == NULL)
+ basprintf(&errors, "%s\n", message);
+ else {
char *new_errors;
- new_errors = concat(errors, message, "\n", (char *) 0);
+ basprintf(&new_errors, "%s%s\n", errors, message);
free(errors);
errors = new_errors;
}
diff --git a/tests/tap/messages.h b/tests/tap/messages.h
index 2b9a7db..0544f2d 100644
--- a/tests/tap/messages.h
+++ b/tests/tap/messages.h
@@ -1,21 +1,37 @@
/*
* Utility functions to test message handling.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2002 Russ Allbery <rra@stanford.edu>
* Copyright 2006, 2007, 2009
- * Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * See LICENSE for licensing terms.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#ifndef TAP_MESSAGES_H
#define TAP_MESSAGES_H 1
#include <config.h>
-#include <portable/macros.h>
+#include <tests/tap/macros.h>
/* A global buffer into which errors_capture stores errors. */
extern char *errors;
diff --git a/tests/tap/perl/Test/RRA.pm b/tests/tap/perl/Test/RRA.pm
new file mode 100644
index 0000000..2d119f4
--- /dev/null
+++ b/tests/tap/perl/Test/RRA.pm
@@ -0,0 +1,222 @@
+# Helper functions for test programs written in Perl.
+#
+# This module provides a collection of helper functions used by test programs
+# written in Perl. This is a general collection of functions that can be used
+# by both C packages with Automake and by stand-alone Perl modules. See
+# Test::RRA::Automake for additional functions specifically for C Automake
+# distributions.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2013
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+package Test::RRA;
+
+use 5.006;
+use strict;
+use warnings;
+
+use Exporter;
+use Test::More;
+
+# For Perl 5.006 compatibility.
+## no critic (ClassHierarchies::ProhibitExplicitISA)
+
+# Declare variables that should be set in BEGIN for robustness.
+our (@EXPORT_OK, @ISA, $VERSION);
+
+# Set $VERSION and everything export-related in a BEGIN block for robustness
+# against circular module loading (not that we load any modules, but
+# consistency is good).
+BEGIN {
+ @ISA = qw(Exporter);
+ @EXPORT_OK = qw(skip_unless_maintainer use_prereq);
+
+ # This version should match the corresponding rra-c-util release, but with
+ # two digits for the minor version, including a leading zero if necessary,
+ # so that it will sort properly.
+ $VERSION = '4.08';
+}
+
+# Skip this test unless maintainer tests are requested. Takes a short
+# description of what tests this script would perform, which is used in the
+# skip message. Calls plan skip_all, which will terminate the program.
+#
+# $description - Short description of the tests
+#
+# Returns: undef
+sub skip_unless_maintainer {
+ my ($description) = @_;
+ if (!$ENV{RRA_MAINTAINER_TESTS}) {
+ plan skip_all => "$description only run for maintainer";
+ }
+ return;
+}
+
+# Attempt to load a module and skip the test if the module could not be
+# loaded. If the module could be loaded, call its import function manually.
+# If the module could not be loaded, calls plan skip_all, which will terminate
+# the program.
+#
+# The special logic here is based on Test::More and is required to get the
+# imports to happen in the caller's namespace.
+#
+# $module - Name of the module to load
+# @imports - Any arguments to import, possibly including a version
+#
+# Returns: undef
+sub use_prereq {
+ my ($module, @imports) = @_;
+
+ # If the first import looks like a version, pass it as a bare string.
+ my $version = q{};
+ if (@imports >= 1 && $imports[0] =~ m{ \A \d+ (?: [.]\d+ )* \z }xms) {
+ $version = shift(@imports);
+ }
+
+ # Get caller information to put imports in the correct package.
+ my ($package) = caller;
+
+ # Do the import with eval, and try to isolate it from the surrounding
+ # context as much as possible. Based heavily on Test::More::_eval.
+ ## no critic (BuiltinFunctions::ProhibitStringyEval)
+ ## no critic (ValuesAndExpressions::ProhibitImplicitNewlines)
+ my ($result, $error, $sigdie);
+ {
+ local $@ = undef;
+ local $! = undef;
+ local $SIG{__DIE__} = undef;
+ $result = eval qq{
+ package $package;
+ use $module $version \@imports;
+ 1;
+ };
+ $error = $@;
+ $sigdie = $SIG{__DIE__} || undef;
+ }
+
+ # If the use failed for any reason, skip the test.
+ if (!$result || $error) {
+ plan skip_all => "$module required for test";
+ }
+
+ # If the module set $SIG{__DIE__}, we cleared that via local. Restore it.
+ ## no critic (Variables::RequireLocalizedPunctuationVars)
+ if (defined($sigdie)) {
+ $SIG{__DIE__} = $sigdie;
+ }
+ return;
+}
+
+1;
+__END__
+
+=for stopwords
+Allbery Allbery's DESC bareword sublicense MERCHANTABILITY NONINFRINGEMENT
+rra-c-util
+
+=head1 NAME
+
+Test::RRA - Support functions for Perl tests
+
+=head1 SYNOPSIS
+
+ use Test::RRA qw(skip_unless_maintainer use_prereq);
+
+ # Skip this test unless maintainer tests are requested.
+ skip_unless_maintainer('Coding style tests');
+
+ # Load modules, skipping the test if they're not available.
+ use_prereq('File::Slurp');
+ use_prereq('Test::Script::Run', '0.04');
+
+=head1 DESCRIPTION
+
+This module collects utility functions that are useful for Perl test
+scripts. It assumes Russ Allbery's Perl module layout and test
+conventions and will only be useful for other people if they use the
+same conventions.
+
+=head1 FUNCTIONS
+
+None of these functions are imported by default. The ones used by a
+script should be explicitly imported.
+
+=over 4
+
+=item skip_unless_maintainer(DESC)
+
+Checks whether RRA_MAINTAINER_TESTS is set in the environment and skips
+the whole test (by calling C<plan skip_all> from Test::More) if it is not.
+DESC is a description of the tests being skipped. A space and C<only run
+for maintainer> will be appended to it and used as the skip reason.
+
+=item use_prereq(MODULE[, VERSION][, IMPORT ...])
+
+Attempts to load MODULE with the given VERSION and import arguments. If
+this fails for any reason, the test will be skipped (by calling C<plan
+skip_all> from Test::More) with a skip reason saying that MODULE is
+required for the test.
+
+VERSION will be passed to C<use> as a version bareword if it looks like a
+version number. The remaining IMPORT arguments will be passed as the
+value of an array.
+
+=back
+
+=head1 AUTHOR
+
+Russ Allbery <rra@stanford.edu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2013 The Board of Trustees of the Leland Stanford Junior
+University.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=head1 SEE ALSO
+
+Test::More(3), Test::RRA::Automake(3), Test::RRA::Config(3)
+
+This module is maintained in the rra-c-util package. The current version
+is available from L<http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+=cut
diff --git a/tests/tap/perl/Test/RRA/Automake.pm b/tests/tap/perl/Test/RRA/Automake.pm
new file mode 100644
index 0000000..2aadb6a
--- /dev/null
+++ b/tests/tap/perl/Test/RRA/Automake.pm
@@ -0,0 +1,362 @@
+# Helper functions for Perl test programs in Automake distributions.
+#
+# This module provides a collection of helper functions used by test programs
+# written in Perl and included in C source distributions that use Automake.
+# They embed knowledge of how I lay out my source trees and test suites with
+# Autoconf and Automake. They may be usable by others, but doing so will
+# require closely following the conventions implemented by the rra-c-util
+# utility collection.
+#
+# All the functions here assume that BUILD and SOURCE are set in the
+# environment. This is normally done via the C TAP Harness runtests wrapper.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2013
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+package Test::RRA::Automake;
+
+use 5.006;
+use strict;
+use warnings;
+
+# For Perl 5.006 compatibility.
+## no critic (ClassHierarchies::ProhibitExplicitISA)
+
+use Exporter;
+use File::Spec;
+use Test::More;
+use Test::RRA::Config qw($LIBRARY_PATH);
+
+# Used below for use lib calls.
+my ($PERL_BLIB_ARCH, $PERL_BLIB_LIB);
+
+# Determine the path to the build tree of any embedded Perl module package in
+# this source package. We do this in a BEGIN block because we're going to use
+# the results in a use lib command below.
+BEGIN {
+ $PERL_BLIB_ARCH = File::Spec->catdir(qw(perl blib arch));
+ $PERL_BLIB_LIB = File::Spec->catdir(qw(perl blib lib));
+
+ # If BUILD is set, we can come up with better values.
+ if (defined($ENV{BUILD})) {
+ my ($vol, $dirs) = File::Spec->splitpath($ENV{BUILD}, 1);
+ my @dirs = File::Spec->splitdir($dirs);
+ pop(@dirs);
+ $PERL_BLIB_ARCH = File::Spec->catdir(@dirs, qw(perl blib arch));
+ $PERL_BLIB_LIB = File::Spec->catdir(@dirs, qw(perl blib lib));
+ }
+}
+
+# Prefer the modules built as part of our source package. Otherwise, we may
+# not find Perl modules while testing, or find the wrong versions.
+use lib $PERL_BLIB_ARCH;
+use lib $PERL_BLIB_LIB;
+
+# Declare variables that should be set in BEGIN for robustness.
+our (@EXPORT_OK, @ISA, $VERSION);
+
+# Set $VERSION and everything export-related in a BEGIN block for robustness
+# against circular module loading (not that we load any modules, but
+# consistency is good).
+BEGIN {
+ @ISA = qw(Exporter);
+ @EXPORT_OK = qw(automake_setup perl_dirs test_file_path);
+
+ # This version should match the corresponding rra-c-util release, but with
+ # two digits for the minor version, including a leading zero if necessary,
+ # so that it will sort properly.
+ $VERSION = '4.08';
+}
+
+# Perl directories to skip globally for perl_dirs. We ignore the perl
+# directory if it exists since, in my packages, it is treated as a Perl module
+# distribution and has its own standalone test suite.
+my @GLOBAL_SKIP = qw(.git perl);
+
+# Perform initial test setup for running a Perl test in an Automake package.
+# This verifies that BUILD and SOURCE are set and then changes directory to
+# the SOURCE directory by default. Sets LD_LIBRARY_PATH if the $LIBRARY_PATH
+# configuration option is set. Calls BAIL_OUT if BUILD or SOURCE are missing
+# or if anything else fails.
+#
+# $args_ref - Reference to a hash of arguments to configure behavior:
+# chdir_build - If set to a true value, changes to BUILD instead of SOURCE
+#
+# Returns: undef
+sub automake_setup {
+ my ($args_ref) = @_;
+
+ # Bail if BUILD or SOURCE are not set.
+ if (!$ENV{BUILD}) {
+ BAIL_OUT('BUILD not defined (run under runtests)');
+ }
+ if (!$ENV{SOURCE}) {
+ BAIL_OUT('SOURCE not defined (run under runtests)');
+ }
+
+ # BUILD or SOURCE will be the test directory. Change to the parent.
+ my $start = $args_ref->{chdir_build} ? $ENV{BUILD} : $ENV{SOURCE};
+ my ($vol, $dirs) = File::Spec->splitpath($start, 1);
+ my @dirs = File::Spec->splitdir($dirs);
+ pop(@dirs);
+ if ($dirs[-1] eq File::Spec->updir) {
+ pop(@dirs);
+ pop(@dirs);
+ }
+ my $root = File::Spec->catpath($vol, File::Spec->catdir(@dirs), q{});
+ chdir($root) or BAIL_OUT("cannot chdir to $root: $!");
+
+ # If BUILD is a subdirectory of SOURCE, add it to the global ignore list.
+ my ($buildvol, $builddirs) = File::Spec->splitpath($ENV{BUILD}, 1);
+ my @builddirs = File::Spec->splitdir($builddirs);
+ pop(@builddirs);
+ if ($buildvol eq $vol && @builddirs == @dirs + 1) {
+ while (@dirs && $builddirs[0] eq $dirs[0]) {
+ shift(@builddirs);
+ shift(@dirs);
+ }
+ if (@builddirs == 1) {
+ push(@GLOBAL_SKIP, $builddirs[0]);
+ }
+ }
+
+ # Set LD_LIBRARY_PATH if the $LIBRARY_PATH configuration option is set.
+ ## no critic (Variables::RequireLocalizedPunctuationVars)
+ if (defined($LIBRARY_PATH)) {
+ @builddirs = File::Spec->splitdir($builddirs);
+ pop(@builddirs);
+ my $libdir = File::Spec->catdir(@builddirs, $LIBRARY_PATH);
+ my $path = File::Spec->catpath($buildvol, $libdir, q{});
+ if (-d "$path/.libs") {
+ $path .= '/.libs';
+ }
+ if ($ENV{LD_LIBRARY_PATH}) {
+ $ENV{LD_LIBRARY_PATH} .= ":$path";
+ } else {
+ $ENV{LD_LIBRARY_PATH} = $path;
+ }
+ }
+ return;
+}
+
+# Returns a list of directories that may contain Perl scripts and that should
+# be passed to Perl test infrastructure that expects a list of directories to
+# recursively check. The list will be all eligible top-level directories in
+# the package except for the tests directory, which is broken out to one
+# additional level. Calls BAIL_OUT on any problems
+#
+# $args_ref - Reference to a hash of arguments to configure behavior:
+# skip - A reference to an array of directories to skip
+#
+# Returns: List of directories possibly containing Perl scripts to test
+sub perl_dirs {
+ my ($args_ref) = @_;
+
+ # Add the global skip list.
+ my @skip = $args_ref->{skip} ? @{ $args_ref->{skip} } : ();
+ push(@skip, @GLOBAL_SKIP);
+
+ # Separate directories to skip under tests from top-level directories.
+ my @skip_tests = grep { m{ \A tests/ }xms } @skip;
+ @skip = grep { !m{ \A tests }xms } @skip;
+ for my $skip_dir (@skip_tests) {
+ $skip_dir =~ s{ \A tests/ }{}xms;
+ }
+
+ # Convert the skip lists into hashes for convenience.
+ my %skip = map { $_ => 1 } @skip, 'tests';
+ my %skip_tests = map { $_ => 1 } @skip_tests;
+
+ # Build the list of top-level directories to test.
+ opendir(my $rootdir, q{.}) or BAIL_OUT("cannot open .: $!");
+ my @dirs = grep { -d $_ && !$skip{$_} } readdir($rootdir);
+ closedir($rootdir);
+ @dirs = File::Spec->no_upwards(@dirs);
+
+ # Add the list of subdirectories of the tests directory.
+ if (-d 'tests') {
+ opendir(my $testsdir, q{tests}) or BAIL_OUT("cannot open tests: $!");
+
+ # Skip if found in %skip_tests or if not a directory.
+ my $is_skipped = sub {
+ my ($dir) = @_;
+ return 1 if $skip_tests{$dir};
+ $dir = File::Spec->catdir('tests', $dir);
+ return -d $dir ? 0 : 1;
+ };
+
+ # Build the filtered list of subdirectories of tests.
+ my @test_dirs = grep { !$is_skipped->($_) } readdir($testsdir);
+ closedir($testsdir);
+ @test_dirs = File::Spec->no_upwards(@test_dirs);
+
+ # Add the tests directory to the start of the directory name.
+ push(@dirs, map { File::Spec->catdir('tests', $_) } @test_dirs);
+ }
+ return @dirs;
+}
+
+# Find a configuration file for the test suite. Searches relative to BUILD
+# first and then SOURCE and returns whichever is found first. Calls BAIL_OUT
+# if the file could not be found.
+#
+# $file - Partial path to the file
+#
+# Returns: Full path to the file
+sub test_file_path {
+ my ($file) = @_;
+ BASE:
+ for my $base ($ENV{BUILD}, $ENV{SOURCE}) {
+ next if !defined($base);
+ if (-f "$base/$file") {
+ return "$base/$file";
+ }
+ }
+ BAIL_OUT("cannot find $file");
+ return;
+}
+
+1;
+__END__
+
+=for stopwords
+Allbery Automake Automake-aware Automake-based rra-c-util ARGS
+subdirectories sublicense MERCHANTABILITY NONINFRINGEMENT
+
+=head1 NAME
+
+Test::RRA::Automake - Automake-aware support functions for Perl tests
+
+=head1 SYNOPSIS
+
+ use Test::RRA::Automake qw(automake_setup perl_dirs test_file_path);
+ automake_setup({ chdir_build => 1 });
+
+ # Paths to directories that may contain Perl scripts.
+ my @dirs = perl_dirs({ skip => [qw(lib)] });
+
+ # Configuration for Kerberos tests.
+ my $keytab = test_file_path('config/keytab');
+
+=head1 DESCRIPTION
+
+This module collects utility functions that are useful for test scripts
+written in Perl and included in a C Automake-based package. They assume
+the layout of a package that uses rra-c-util and C TAP Harness for the
+test structure.
+
+Loading this module will also add the directories C<perl/blib/arch> and
+C<perl/blib/lib> to the Perl library search path, relative to BUILD if
+that environment variable is set. This is harmless for C Automake
+projects that don't contain an embedded Perl module, and for those
+projects that do, this will allow subsequent C<use> calls to find modules
+that are built as part of the package build process.
+
+The automake_setup() function should be called before calling any other
+functions provided by this module.
+
+=head1 FUNCTIONS
+
+None of these functions are imported by default. The ones used by a
+script should be explicitly imported. On failure, all of these functions
+call BAIL_OUT (from Test::More).
+
+=over 4
+
+=item automake_setup([ARGS])
+
+Verifies that the BUILD and SOURCE environment variables are set and
+then changes directory to the top of the source tree (which is one
+directory up from the SOURCE path, since SOURCE points to the top of
+the tests directory).
+
+If ARGS is given, it should be a reference to a hash of configuration
+options. Only one option is supported: C<chdir_build>. If it is set
+to a true value, automake_setup() changes directories to the top of
+the build tree instead.
+
+=item perl_dirs([ARGS])
+
+Returns a list of directories that may contain Perl scripts that should be
+tested by test scripts that test all Perl in the source tree (such as
+syntax or coding style checks). The paths will be simple directory names
+relative to the current directory or two-part directory names under the
+F<tests> directory. (Directories under F<tests> are broken out separately
+since it's common to want to apply different policies to different
+subdirectories of F<tests>.)
+
+If ARGS is given, it should be a reference to a hash of configuration
+options. Only one option is supported: C<skip>, whose value should be a
+reference to an array of additional top-level directories or directories
+starting with C<tests/> that should be skipped.
+
+=item test_file_path(FILE)
+
+Given FILE, which should be a relative path, locates that file relative to
+the test directory in either the source or build tree. FILE will be
+checked for relative to the environment variable BUILD first, and then
+relative to SOURCE. test_file_path() returns the full path to FILE or
+calls BAIL_OUT if FILE could not be found.
+
+=back
+
+=head1 AUTHOR
+
+Russ Allbery <rra@stanford.edu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2013 The Board of Trustees of the Leland Stanford Junior
+University.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=head1 SEE ALSO
+
+Test::More(3), Test::RRA(3), Test::RRA::Config(3)
+
+The C TAP Harness test driver and libraries for TAP-based C testing are
+available from L<http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+
+This module is maintained in the rra-c-util package. The current version
+is available from L<http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+=cut
diff --git a/tests/tap/perl/Test/RRA/Config.pm b/tests/tap/perl/Test/RRA/Config.pm
new file mode 100644
index 0000000..0091b26
--- /dev/null
+++ b/tests/tap/perl/Test/RRA/Config.pm
@@ -0,0 +1,200 @@
+# Configuration for Perl test cases.
+#
+# In order to reuse the same Perl test cases in multiple packages, I use a
+# configuration file to store some package-specific data. This module loads
+# that configuration and provides the namespace for the configuration
+# settings.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+package Test::RRA::Config;
+
+use 5.006;
+use strict;
+use warnings;
+
+# For Perl 5.006 compatibility.
+## no critic (ClassHierarchies::ProhibitExplicitISA)
+
+use Exporter;
+use Test::More;
+
+# Declare variables that should be set in BEGIN for robustness.
+our (@EXPORT_OK, @ISA, $VERSION);
+
+# Set $VERSION and everything export-related in a BEGIN block for robustness
+# against circular module loading (not that we load any modules, but
+# consistency is good).
+BEGIN {
+ @ISA = qw(Exporter);
+ @EXPORT_OK = qw(
+ $COVERAGE_LEVEL @COVERAGE_SKIP_TESTS @CRITIC_IGNORE $LIBRARY_PATH
+ $MINIMUM_VERSION %MINIMUM_VERSION @POD_COVERAGE_EXCLUDE
+ );
+
+ # This version should match the corresponding rra-c-util release, but with
+ # two digits for the minor version, including a leading zero if necessary,
+ # so that it will sort properly.
+ $VERSION = '4.08';
+}
+
+# If BUILD or SOURCE are set in the environment, look for data/perl.conf under
+# those paths for a C Automake package. Otherwise, look in t/data/perl.conf
+# for a standalone Perl module. Don't use Test::RRA::Automake since it may
+# not exist.
+our $PATH;
+for my $base ($ENV{BUILD}, $ENV{SOURCE}, 't') {
+ next if !defined($base);
+ my $path = "$base/data/perl.conf";
+ if (-r $path) {
+ $PATH = $path;
+ last;
+ }
+}
+if (!defined($PATH)) {
+ BAIL_OUT('cannot find data/perl.conf');
+}
+
+# Pre-declare all of our variables and set any defaults.
+our $COVERAGE_LEVEL = 100;
+our @COVERAGE_SKIP_TESTS;
+our @CRITIC_IGNORE;
+our $LIBRARY_PATH;
+our $MINIMUM_VERSION = '5.008';
+our %MINIMUM_VERSION;
+our @POD_COVERAGE_EXCLUDE;
+
+# Load the configuration.
+if (!do($PATH)) {
+ my $error = $@ || $! || 'loading file did not return true';
+ BAIL_OUT("cannot load data/perl.conf: $error");
+}
+
+1;
+__END__
+
+=for stopwords
+Allbery rra-c-util Automake perlcritic .libs namespace sublicense
+MERCHANTABILITY NONINFRINGEMENT
+
+=head1 NAME
+
+Test::RRA::Config - Perl test configuration
+
+=head1 SYNOPSIS
+
+ use Test::RRA::Config qw($MINIMUM_VERSION);
+ print "Required Perl version is $MINIMUM_VERSION\n";
+
+=head1 DESCRIPTION
+
+Test::RRA::Config encapsulates per-package configuration for generic Perl
+test programs that are shared between multiple packages using the
+rra-c-util infrastructure. It handles locating and loading the test
+configuration file for both C Automake packages and stand-alone Perl
+modules.
+
+Test::RRA::Config looks for a file named F<data/perl.conf> relative to the
+root of the test directory. That root is taken from the environment
+variables BUILD or SOURCE (in that order) if set, which will be the case
+for C Automake packages using C TAP Harness. If neither is set, it
+expects the root of the test directory to be a directory named F<t>
+relative to the current directory, which will be the case for stand-alone
+Perl modules.
+
+The following variables are supported:
+
+=over 4
+
+=item $COVERAGE_LEVEL
+
+The coverage level achieved by the test suite for Perl test coverage
+testing using Test::Strict, as a percentage. The test will fail if test
+coverage less than this percentage is achieved. If not given, defaults
+to 100.
+
+=item @COVERAGE_SKIP_TESTS
+
+Directories under F<t> whose tests should be skipped when doing coverage
+testing. This can be tests that won't contribute to coverage or tests
+that don't run properly under Devel::Cover for some reason (such as ones
+that use taint checking). F<docs> and F<style> will always be skipped
+regardless of this setting.
+
+=item @CRITIC_IGNORE
+
+Additional directories to ignore when doing recursive perlcritic testing.
+The contents of this directory must be either top-level directory names or
+directory names starting with F<tests/>.
+
+=item $LIBRARY_PATH
+
+Add this directory (or a .libs subdirectory) relative to the top of the
+source tree to LD_LIBRARY_PATH when checking the syntax of Perl modules.
+This may be required to pick up libraries that are used by in-tree Perl
+modules so that Perl scripts can pass a syntax check.
+
+=item $MINIMUM_VERSION
+
+Default minimum version requirement for included Perl scripts. If not
+given, defaults to 5.008.
+
+=item %MINIMUM_VERSION
+
+Minimum version exceptions for specific directories. The keys should be
+minimum versions of Perl to enforce. The value for each key should be a
+reference to an array of either top-level directory names or directory
+names starting with F<tests/>. All files in those directories will have
+that minimum Perl version constraint imposed instead of $MINIMUM_VERSION.
+
+=item @POD_COVERAGE_EXCLUDE
+
+Regexes that match method names that should be excluded from POD coverage
+testing. Normally, all methods have to be documented in the POD for a
+Perl module, but methods matching any of these regexes will be considered
+private and won't require documentation.
+
+=back
+
+No variables are exported by default, but the variables can be imported
+into the local namespace to avoid long variable names.
+
+=head1 AUTHOR
+
+Russ Allbery <rra@stanford.edu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2013 The Board of Trustees of the Leland Stanford Junior
+University.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=head1 SEE ALSO
+
+Test::RRA(3), Test::RRA::Automake(3)
+
+This module is maintained in the rra-c-util package. The current version
+is available from L<http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+The C TAP Harness test driver and libraries for TAP-based C testing are
+available from L<http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+
+=cut
diff --git a/tests/tap/process.c b/tests/tap/process.c
index 16154c7..8ed4cfd 100644
--- a/tests/tap/process.c
+++ b/tests/tap/process.c
@@ -1,18 +1,37 @@
/*
* Utility functions for tests that use subprocesses.
*
- * Provides utility functions for subprocess manipulation. Currently, only
- * one utility function is provided: is_function_output, which runs a function
- * in a subprocess and checks its output and exit status against expected
- * values.
+ * Provides utility functions for subprocess manipulation. Specifically,
+ * provides a function, run_setup, which runs a command and bails if it fails,
+ * using its error message as the bail output, and is_function_output, which
+ * runs a function in a subprocess and checks its output and exit status
+ * against expected values.
*
- * Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * See LICENSE for licensing terms.
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Copyright 2002, 2004, 2005 Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010, 2011
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
@@ -22,26 +41,24 @@
#include <tests/tap/basic.h>
#include <tests/tap/process.h>
-#include <util/xmalloc.h>
+#include <tests/tap/string.h>
/*
* Given a function, an expected exit status, and expected output, runs that
* function in a subprocess, capturing stdout and stderr via a pipe, and
- * compare the combination of stdout and stderr with the expected output and
- * the exit status with the expected status. Expects the function to always
- * exit (not die from a signal).
+ * returns the function output in newly allocated memory. Also captures the
+ * process exit status.
*/
-void
-is_function_output(test_function_type function, int status, const char *output,
- const char *format, ...)
+static void
+run_child_function(test_function_type function, void *data, int *status,
+ char **output)
{
int fds[2];
pid_t child;
- char *buf, *msg;
+ char *buf;
ssize_t count, ret, buflen;
int rval;
- va_list args;
/* Flush stdout before we start to avoid odd forking issues. */
fflush(stdout);
@@ -61,7 +78,7 @@ is_function_output(test_function_type function, int status, const char *output,
_exit(255);
/* Now, run the function and exit successfully if it returns. */
- (*function)();
+ (*function)(data);
fflush(stdout);
_exit(0);
} else {
@@ -71,7 +88,7 @@ is_function_output(test_function_type function, int status, const char *output,
*/
close(fds[1]);
buflen = BUFSIZ;
- buf = xmalloc(buflen);
+ buf = bmalloc(buflen);
count = 0;
do {
ret = read(fds[0], buf + count, buflen - count - 1);
@@ -79,18 +96,41 @@ is_function_output(test_function_type function, int status, const char *output,
count += ret;
if (count >= buflen - 1) {
buflen += BUFSIZ;
- buf = xrealloc(buf, buflen);
+ buf = brealloc(buf, buflen);
}
} while (ret > 0);
buf[count < 0 ? 0 : count] = '\0';
if (waitpid(child, &rval, 0) == (pid_t) -1)
sysbail("waitpid failed");
+ close(fds[0]);
}
+ /* Store the output and return. */
+ *status = rval;
+ *output = buf;
+}
+
+
+/*
+ * Given a function, data to pass to that function, an expected exit status,
+ * and expected output, runs that function in a subprocess, capturing stdout
+ * and stderr via a pipe, and compare the combination of stdout and stderr
+ * with the expected output and the exit status with the expected status.
+ * Expects the function to always exit (not die from a signal).
+ */
+void
+is_function_output(test_function_type function, void *data, int status,
+ const char *output, const char *format, ...)
+{
+ char *buf, *msg;
+ int rval;
+ va_list args;
+
+ run_child_function(function, data, &rval, &buf);
+
/* Now, check the results against what we expected. */
va_start(args, format);
- if (xvasprintf(&msg, format, args) < 0)
- bail("cannot format test description");
+ bvasprintf(&msg, format, args);
va_end(args);
ok(WIFEXITED(rval), "%s (exited)", msg);
is_int(status, WEXITSTATUS(rval), "%s (status)", msg);
@@ -98,3 +138,40 @@ is_function_output(test_function_type function, int status, const char *output,
free(buf);
free(msg);
}
+
+
+/*
+ * A helper function for run_setup. This is a function to run an external
+ * command, suitable for passing into run_child_function. The expected
+ * argument must be an argv array, with argv[0] being the command to run.
+ */
+static void
+exec_command(void *data)
+{
+ char *const *argv = data;
+
+ execvp(argv[0], argv);
+}
+
+
+/*
+ * Given a command expressed as an argv struct, with argv[0] the name or path
+ * to the command, run that command. If it exits with a non-zero status, use
+ * the part of its output up to the first newline as the error message when
+ * calling bail.
+ */
+void
+run_setup(const char *const argv[])
+{
+ char *output, *p;
+ int status;
+
+ run_child_function(exec_command, (void *) argv, &status, &output);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ p = strchr(output, '\n');
+ if (p != NULL)
+ *p = '\0';
+ bail("%s", output);
+ }
+ free(output);
+}
diff --git a/tests/tap/process.h b/tests/tap/process.h
index b7d3b11..df74b5f 100644
--- a/tests/tap/process.h
+++ b/tests/tap/process.h
@@ -1,36 +1,64 @@
/*
* Utility functions for tests that use subprocesses.
*
- * Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * See LICENSE for licensing terms.
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#ifndef TAP_PROCESS_H
#define TAP_PROCESS_H 1
#include <config.h>
-#include <portable/macros.h>
+#include <tests/tap/macros.h>
BEGIN_DECLS
/*
* Run a function in a subprocess and check the exit status and expected
* output (stdout and stderr combined) against the provided values. Expects
- * the function to always exit (not die from a signal).
+ * the function to always exit (not die from a signal). data is optional data
+ * that's passed into the function as its only argument.
*
* This reports as three separate tests: whether the function exited rather
* than was killed, whether the exit status was correct, and whether the
* output was correct.
*/
-typedef void (*test_function_type)(void);
-void is_function_output(test_function_type, int status, const char *output,
- const char *format, ...)
- __attribute__((__format__(printf, 4, 5)));
+typedef void (*test_function_type)(void *);
+void is_function_output(test_function_type, void *data, int status,
+ const char *output, const char *format, ...)
+ __attribute__((__format__(printf, 5, 6), __nonnull__(1)));
+
+/*
+ * Run a setup program. Takes the program to run and its arguments as an argv
+ * vector, where argv[0] must be either the full path to the program or the
+ * program name if the PATH should be searched. If the program does not exit
+ * successfully, call bail, with the error message being the output from the
+ * program.
+ */
+void run_setup(const char *const argv[])
+ __attribute__((__nonnull__));
END_DECLS
diff --git a/tests/tap/remctl.sh b/tests/tap/remctl.sh
index 9e01bcf..2fd6681 100644
--- a/tests/tap/remctl.sh
+++ b/tests/tap/remctl.sh
@@ -1,40 +1,67 @@
# Shell function library to start and stop remctld
#
+# Note that while many of the functions in this library could benefit from
+# using "local" to avoid possibly hammering global variables, Solaris /bin/sh
+# doesn't support local and this library aspires to be portable to Solaris
+# Bourne shell. Instead, all private variables are prefixed with "tap_".
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2009, 2012
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# See LICENSE for licensing terms.
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
# Start remctld. Takes the path to remctld, which may be found via configure,
# and the path to the configuration file.
remctld_start () {
- local keytab principal
- rm -f "$BUILD/data/remctld.pid"
- keytab=`test_file_path data/test.keytab`
- principal=`test_file_path data/test.principal`
- principal=`cat "$principal" 2>/dev/null`
- if [ -z "$keytab" ] || [ -z "$principal" ] ; then
+ tap_pidfile=`test_tmpdir`/remctld.pid
+ rm -f "$tap_pidfile"
+ tap_keytab=`test_file_path config/keytab`
+ tap_principal=`test_file_path config/principal`
+ tap_principal=`cat "$tap_principal" 2>/dev/null`
+ if [ -z "$tap_keytab" ] || [ -z "$tap_principal" ] ; then
return 1
fi
if [ -n "$VALGRIND" ] ; then
( "$VALGRIND" --log-file=valgrind.%p --leak-check=full "$1" -m \
- -p 14373 -s "$principal" -P "$BUILD/data/remctld.pid" -f "$2" -d \
- -S -F -k "$keytab" &)
+ -p 14373 -s "$tap_principal" -P "$tap_pidfile" -f "$2" -d -S -F \
+ -k "$tap_keytab" &)
[ -f "$BUILD/data/remctld.pid" ] || sleep 5
else
- ( "$1" -m -p 14373 -s "$principal" -P "$BUILD/data/remctld.pid" \
- -f "$2" -d -S -F -k "$keytab" &)
+ ( "$1" -m -p 14373 -s "$tap_principal" -P "$tap_pidfile" -f "$2" \
+ -d -S -F -k "$tap_keytab" &)
fi
- [ -f "$BUILD/data/remctld.pid" ] || sleep 1
- if [ ! -f "$BUILD/data/remctld.pid" ] ; then
+ [ -f "$tap_pidfile" ] || sleep 1
+ [ -f "$tap_pidfile" ] || sleep 1
+ if [ ! -f "$tap_pidfile" ] ; then
bail 'remctld did not start'
fi
}
# Stop remctld and clean up.
remctld_stop () {
- if [ -f "$BUILD/data/remctld.pid" ] ; then
- kill -TERM `cat "$BUILD/data/remctld.pid"`
- rm -f "$BUILD/data/remctld.pid"
+ tap_pidfile=`test_tmpdir`/remctld.pid
+ if [ -f "$tap_pidfile" ] ; then
+ kill -TERM `cat "$tap_pidfile"`
+ rm -f "$tap_pidfile"
fi
}
diff --git a/tests/tap/string.c b/tests/tap/string.c
new file mode 100644
index 0000000..f5c965c
--- /dev/null
+++ b/tests/tap/string.c
@@ -0,0 +1,65 @@
+/*
+ * String utilities for the TAP protocol.
+ *
+ * Additional string utilities that can't be included with C TAP Harness
+ * because they rely on additional portability code from rra-c-util.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2011, 2012 Russ Allbery <rra@stanford.edu>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <tests/tap/basic.h>
+#include <tests/tap/string.h>
+
+
+/*
+ * vsprintf into a newly allocated string, reporting a fatal error with bail
+ * on failure.
+ */
+void
+bvasprintf(char **strp, const char *fmt, va_list args)
+{
+ int status;
+
+ status = vasprintf(strp, fmt, args);
+ if (status < 0)
+ sysbail("failed to allocate memory for vasprintf");
+}
+
+
+/*
+ * sprintf into a newly allocated string, reporting a fatal error with bail on
+ * failure.
+ */
+void
+basprintf(char **strp, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ bvasprintf(strp, fmt, args);
+ va_end(args);
+}
diff --git a/tests/tap/string.h b/tests/tap/string.h
new file mode 100644
index 0000000..2f699e4
--- /dev/null
+++ b/tests/tap/string.h
@@ -0,0 +1,49 @@
+/*
+ * String utilities for the TAP protocol.
+ *
+ * Additional string utilities that can't be included with C TAP Harness
+ * because they rely on additional portability code from rra-c-util.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2011, 2012 Russ Allbery <rra@stanford.edu>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TAP_STRING_H
+#define TAP_STRING_H 1
+
+#include <config.h>
+#include <tests/tap/macros.h>
+
+#include <stdarg.h> /* va_list */
+
+BEGIN_DECLS
+
+/* sprintf into an allocated string, calling bail on any failure. */
+void basprintf(char **, const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 2, 3)));
+void bvasprintf(char **, const char *, va_list)
+ __attribute__((__nonnull__));
+
+END_DECLS
+
+#endif /* !TAP_STRING_H */
diff --git a/tests/util/messages-krb5-t.c b/tests/util/messages-krb5-t.c
index 02d8f92..e3ffe75 100644
--- a/tests/util/messages-krb5-t.c
+++ b/tests/util/messages-krb5-t.c
@@ -1,10 +1,30 @@
/*
* Test suite for Kerberos error handling routines.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2010 Board of Trustees, Leland Stanford Jr. University
+ * Copyright 2010, 2011
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * See LICENSE for licensing terms.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
@@ -13,6 +33,7 @@
#include <tests/tap/basic.h>
#include <tests/tap/process.h>
+#include <util/macros.h>
#include <util/messages-krb5.h>
#include <util/messages.h>
#include <util/xmalloc.h>
@@ -22,7 +43,7 @@
* Test functions.
*/
static void
-test_warn(void)
+test_warn(void *data UNUSED)
{
krb5_context ctx;
krb5_error_code code;
@@ -40,7 +61,7 @@ test_warn(void)
}
static void
-test_die(void)
+test_die(void *data UNUSED)
{
krb5_context ctx;
krb5_error_code code;
@@ -80,20 +101,20 @@ main(void)
message = krb5_get_error_message(ctx, code);
xasprintf(&wanted, "principal parse failed: %s\n", message);
- is_function_output(test_warn, 0, wanted, "warn_krb5");
- is_function_output(test_die, 1, wanted, "die_krb5");
+ is_function_output(test_warn, NULL, 0, wanted, "warn_krb5");
+ is_function_output(test_die, NULL, 1, wanted, "die_krb5");
free(wanted);
message_program_name = "msg-test";
xasprintf(&wanted, "msg-test: principal parse failed: %s\n", message);
- is_function_output(test_warn, 0, wanted, "warn_krb5 with name");
- is_function_output(test_die, 1, wanted, "die_krb5 with name");
+ is_function_output(test_warn, NULL, 0, wanted, "warn_krb5 with name");
+ is_function_output(test_die, NULL, 1, wanted, "die_krb5 with name");
free(wanted);
message_handlers_warn(0);
- is_function_output(test_warn, 0, "", "warn_krb5 with no handlers");
+ is_function_output(test_warn, NULL, 0, "", "warn_krb5 with no handlers");
message_handlers_die(0);
- is_function_output(test_die, 1, "", "warn_krb5 with no handlers");
+ is_function_output(test_die, NULL, 1, "", "warn_krb5 with no handlers");
return 0;
}
diff --git a/tests/util/messages-t.c b/tests/util/messages-t.c
index a58f82c..54f1cf1 100644
--- a/tests/util/messages-t.c
+++ b/tests/util/messages-t.c
@@ -1,14 +1,31 @@
/*
* Test suite for error handling routines.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ * Copyright 2002, 2004, 2005 Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010, 2011, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * See LICENSE for licensing terms.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
@@ -21,7 +38,7 @@
#include <tests/tap/basic.h>
#include <tests/tap/process.h>
-#include <util/concat.h>
+#include <util/macros.h>
#include <util/messages.h>
#include <util/xmalloc.h>
@@ -29,24 +46,27 @@
/*
* Test functions.
*/
-static void test1(void) { warn("warning"); }
-static void test2(void) { die("fatal"); }
-static void test3(void) { errno = EPERM; syswarn("permissions"); }
-static void test4(void) { errno = EACCES; sysdie("fatal access"); }
-static void test5(void) {
+static void test1(void *data UNUSED) { warn("warning"); }
+static void test2(void *data UNUSED) { die("fatal"); }
+static void test3(void *data UNUSED) { errno = EPERM; syswarn("permissions"); }
+static void test4(void *data UNUSED) {
+ errno = EACCES;
+ sysdie("fatal access");
+}
+static void test5(void *data UNUSED) {
message_program_name = "test5";
warn("warning");
}
-static void test6(void) {
+static void test6(void *data UNUSED) {
message_program_name = "test6";
die("fatal");
}
-static void test7(void) {
+static void test7(void *data UNUSED) {
message_program_name = "test7";
errno = EPERM;
syswarn("perms %d", 7);
}
-static void test8(void) {
+static void test8(void *data UNUSED) {
message_program_name = "test8";
errno = EACCES;
sysdie("%st%s", "fa", "al");
@@ -54,17 +74,17 @@ static void test8(void) {
static int return10(void) { return 10; }
-static void test9(void) {
+static void test9(void *data UNUSED) {
message_fatal_cleanup = return10;
die("fatal");
}
-static void test10(void) {
+static void test10(void *data UNUSED) {
message_program_name = 0;
message_fatal_cleanup = return10;
errno = EPERM;
sysdie("fatal perm");
}
-static void test11(void) {
+static void test11(void *data UNUSED) {
message_program_name = "test11";
message_fatal_cleanup = return10;
errno = EPERM;
@@ -72,61 +92,61 @@ static void test11(void) {
sysdie("fatal");
}
-static void log_msg(int len, const char *format, va_list args, int error) {
- fprintf(stderr, "%d %d ", len, error);
+static void log_msg(size_t len, const char *format, va_list args, int error) {
+ fprintf(stderr, "%lu %d ", (unsigned long) len, error);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
}
-static void test12(void) {
+static void test12(void *data UNUSED) {
message_handlers_warn(1, log_msg);
warn("warning");
}
-static void test13(void) {
+static void test13(void *data UNUSED) {
message_handlers_die(1, log_msg);
die("fatal");
}
-static void test14(void) {
+static void test14(void *data UNUSED) {
message_handlers_warn(2, log_msg, log_msg);
errno = EPERM;
syswarn("warning");
}
-static void test15(void) {
+static void test15(void *data UNUSED) {
message_handlers_die(2, log_msg, log_msg);
message_fatal_cleanup = return10;
errno = EPERM;
sysdie("fatal");
}
-static void test16(void) {
+static void test16(void *data UNUSED) {
message_handlers_warn(2, message_log_stderr, log_msg);
message_program_name = "test16";
errno = EPERM;
syswarn("warning");
}
-static void test17(void) { notice("notice"); }
-static void test18(void) {
+static void test17(void *data UNUSED) { notice("notice"); }
+static void test18(void *data UNUSED) {
message_program_name = "test18";
notice("notice");
}
-static void test19(void) { debug("debug"); }
-static void test20(void) {
+static void test19(void *data UNUSED) { debug("debug"); }
+static void test20(void *data UNUSED) {
message_handlers_notice(1, log_msg);
notice("foo");
}
-static void test21(void) {
+static void test21(void *data UNUSED) {
message_handlers_debug(1, message_log_stdout);
message_program_name = "test23";
debug("baz");
}
-static void test22(void) {
+static void test22(void *data UNUSED) {
message_handlers_die(0);
die("hi mom!");
}
-static void test23(void) {
+static void test23(void *data UNUSED) {
message_handlers_warn(0);
warn("this is a test");
}
-static void test24(void) {
+static void test24(void *data UNUSED) {
notice("first");
message_handlers_notice(0);
notice("second");
@@ -145,9 +165,9 @@ test_strerror(int status, const char *output, int error,
{
char *full_output, *name;
- full_output = concat(output, ": ", strerror(error), "\n", (char *) NULL);
+ xasprintf(&full_output, "%s: %s\n", output, strerror(error));
xasprintf(&name, "strerror %lu", testnum / 3 + 1);
- is_function_output(function, status, full_output, "%s", name);
+ is_function_output(function, NULL, status, full_output, "%s", name);
free(full_output);
free(name);
}
@@ -164,43 +184,43 @@ main(void)
plan(24 * 3);
- is_function_output(test1, 0, "warning\n", "test1");
- is_function_output(test2, 1, "fatal\n", "test2");
+ is_function_output(test1, NULL, 0, "warning\n", "test1");
+ is_function_output(test2, NULL, 1, "fatal\n", "test2");
test_strerror(0, "permissions", EPERM, test3);
test_strerror(1, "fatal access", EACCES, test4);
- is_function_output(test5, 0, "test5: warning\n", "test5");
- is_function_output(test6, 1, "test6: fatal\n", "test6");
+ is_function_output(test5, NULL, 0, "test5: warning\n", "test5");
+ is_function_output(test6, NULL, 1, "test6: fatal\n", "test6");
test_strerror(0, "test7: perms 7", EPERM, test7);
test_strerror(1, "test8: fatal", EACCES, test8);
- is_function_output(test9, 10, "fatal\n", "test9");
+ is_function_output(test9, NULL, 10, "fatal\n", "test9");
test_strerror(10, "fatal perm", EPERM, test10);
test_strerror(10, "1st test11: fatal", EPERM, test11);
- is_function_output(test12, 0, "7 0 warning\n", "test12");
- is_function_output(test13, 1, "5 0 fatal\n", "test13");
+ is_function_output(test12, NULL, 0, "7 0 warning\n", "test12");
+ is_function_output(test13, NULL, 1, "5 0 fatal\n", "test13");
sprintf(buff, "%d", EPERM);
xasprintf(&output, "7 %d warning\n7 %d warning\n", EPERM, EPERM);
- is_function_output(test14, 0, output, "test14");
+ is_function_output(test14, NULL, 0, output, "test14");
free(output);
xasprintf(&output, "5 %d fatal\n5 %d fatal\n", EPERM, EPERM);
- is_function_output(test15, 10, output, "test15");
+ is_function_output(test15, NULL, 10, output, "test15");
free(output);
xasprintf(&output, "test16: warning: %s\n7 %d warning\n", strerror(EPERM),
EPERM);
- is_function_output(test16, 0, output, "test16");
+ is_function_output(test16, NULL, 0, output, "test16");
free(output);
- is_function_output(test17, 0, "notice\n", "test17");
- is_function_output(test18, 0, "test18: notice\n", "test18");
- is_function_output(test19, 0, "", "test19");
- is_function_output(test20, 0, "3 0 foo\n", "test20");
- is_function_output(test21, 0, "test23: baz\n", "test21");
+ is_function_output(test17, NULL, 0, "notice\n", "test17");
+ is_function_output(test18, NULL, 0, "test18: notice\n", "test18");
+ is_function_output(test19, NULL, 0, "", "test19");
+ is_function_output(test20, NULL, 0, "3 0 foo\n", "test20");
+ is_function_output(test21, NULL, 0, "test23: baz\n", "test21");
/* Make sure that it's possible to turn off a message type entirely. */
- is_function_output(test22, 1, "", "test22");
- is_function_output(test23, 0, "", "test23");
- is_function_output(test24, 0, "first\nthird\n", "test24");
+ is_function_output(test22, NULL, 1, "", "test22");
+ is_function_output(test23, NULL, 0, "", "test23");
+ is_function_output(test24, NULL, 0, "first\nthird\n", "test24");
return 0;
}
diff --git a/tests/util/xmalloc-t b/tests/util/xmalloc-t
index 67d95f6..b6c6dfd 100755
--- a/tests/util/xmalloc-t
+++ b/tests/util/xmalloc-t
@@ -2,14 +2,31 @@
#
# Test suite for xmalloc and friends.
#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2008, 2009, 2010 Board of Trustees, Leland Stanford Jr. University
-# Copyright 2004, 2005, 2006
-# by Internet Systems Consortium, Inc. ("ISC")
-# Copyright 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003 by The Internet Software Consortium and Rich Salz
+# Copyright 2000, 2001, 2006 Russ Allbery <rra@stanford.edu>
+# Copyright 2008, 2009, 2010, 2012
+# The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
#
-# See LICENSE for licensing terms.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
. "$SOURCE/tap/libtap.sh"
cd "$BUILD/util"
@@ -24,18 +41,16 @@ ok_xmalloc () {
shift
w_output="$1"
shift
- output=`./xmalloc "$@" 2>&1`
+ output=`strip_colon_error ./xmalloc "$@" 2>&1`
status=$?
- if [ "$w_status" -ne 0 ] ; then
- output=`echo "$output" | sed 's/:.*//'`
- fi
if [ $status = $w_status ] && [ x"$output" = x"$w_output" ] ; then
ok "$desc" true
elif [ $status = 2 ] ; then
+ diag "$output"
skip "no data limit support"
else
- echo "# saw: ($status) $output"
- echo "# not: ($w_status) $w_output"
+ diag "saw: ($status) $output"
+ diag "not: ($w_status) $w_output"
ok "$desc" false
fi
}
@@ -53,75 +68,76 @@ plan 36
# First run the tests expected to succeed.
ok_xmalloc "malloc small" 0 "" "m" "21" "0"
-ok_xmalloc "malloc large" 0 "" "m" "3500000" "0"
+ok_xmalloc "malloc large" 0 "" "m" "5500000" "0"
ok_xmalloc "malloc zero" 0 "" "m" "0" "0"
ok_xmalloc "realloc small" 0 "" "r" "21" "0"
-ok_xmalloc "realloc large" 0 "" "r" "3500000" "0"
+ok_xmalloc "realloc large" 0 "" "r" "5500000" "0"
ok_xmalloc "strdup small" 0 "" "s" "21" "0"
-ok_xmalloc "strdup large" 0 "" "s" "3500000" "0"
+ok_xmalloc "strdup large" 0 "" "s" "5500000" "0"
ok_xmalloc "strndup small" 0 "" "n" "21" "0"
-ok_xmalloc "strndup large" 0 "" "n" "3500000" "0"
+ok_xmalloc "strndup large" 0 "" "n" "5500000" "0"
ok_xmalloc "calloc small" 0 "" "c" "24" "0"
-ok_xmalloc "calloc large" 0 "" "c" "3500000" "0"
+ok_xmalloc "calloc large" 0 "" "c" "5500000" "0"
ok_xmalloc "asprintf small" 0 "" "a" "24" "0"
-ok_xmalloc "asprintf large" 0 "" "a" "3500000" "0"
+ok_xmalloc "asprintf large" 0 "" "a" "5500000" "0"
ok_xmalloc "vasprintf small" 0 "" "v" "24" "0"
-ok_xmalloc "vasprintf large" 0 "" "v" "3500000" "0"
+ok_xmalloc "vasprintf large" 0 "" "v" "5500000" "0"
-# Now limit our memory to 3.5MB and then try the large ones again, all of
+# Now limit our memory to 5.5MB and then try the large ones again, all of
# which should fail.
#
# The exact memory limits used here are essentially black magic. They need to
# be large enough to allow the program to be loaded and do small allocations,
# but not so large that we can't reasonably expect to allocate that much
-# memory normally. 3.5MB seems to work reasonably well on both Solaris and
-# Linux.
+# memory normally. The amount of memory required varies a lot based on what
+# shared libraries are loaded, and if it's too small, all memory allocations
+# fail. 5.5MB seems to work reasonably well on both Solaris and Linux.
#
# We assume that there are enough miscellaneous allocations that an allocation
# exactly as large as the limit will always fail.
ok_xmalloc "malloc fail" 1 \
- "failed to malloc 3500000 bytes at xmalloc.c line 38" \
- "m" "3500000" "3500000"
+ "failed to malloc 5500000 bytes at xmalloc.c line 38" \
+ "m" "5500000" "5500000"
ok_xmalloc "realloc fail" 1 \
- "failed to realloc 3500000 bytes at xmalloc.c line 66" \
- "r" "3500000" "3500000"
+ "failed to realloc 5500000 bytes at xmalloc.c line 66" \
+ "r" "5500000" "5500000"
ok_xmalloc "strdup fail" 1 \
- "failed to strdup 3500000 bytes at xmalloc.c line 97" \
- "s" "3500000" "3500000"
+ "failed to strdup 5500000 bytes at xmalloc.c line 97" \
+ "s" "5500000" "5500000"
ok_xmalloc "strndup fail" 1 \
- "failed to strndup 3500000 bytes at xmalloc.c line 124" \
- "n" "3500000" "3500000"
+ "failed to strndup 5500000 bytes at xmalloc.c line 143" \
+ "n" "5500000" "5500000"
ok_xmalloc "calloc fail" 1 \
- "failed to calloc 3500000 bytes at xmalloc.c line 148" \
- "c" "3500000" "3500000"
+ "failed to calloc 5500000 bytes at xmalloc.c line 167" \
+ "c" "5500000" "5500000"
ok_xmalloc "asprintf fail" 1 \
- "failed to asprintf 3500000 bytes at xmalloc.c line 172" \
- "a" "3500000" "3500000"
+ "failed to asprintf 5500000 bytes at xmalloc.c line 191" \
+ "a" "5500000" "5500000"
ok_xmalloc "vasprintf fail" 1 \
- "failed to vasprintf 3500000 bytes at xmalloc.c line 192" \
- "v" "3500000" "3500000"
+ "failed to vasprintf 5500000 bytes at xmalloc.c line 210" \
+ "v" "5500000" "5500000"
# Check our custom error handler.
-ok_xmalloc "malloc custom" 1 "malloc 3500000 xmalloc.c 38" \
- "M" "3500000" "3500000"
-ok_xmalloc "realloc custom" 1 "realloc 3500000 xmalloc.c 66" \
- "R" "3500000" "3500000"
-ok_xmalloc "strdup custom" 1 "strdup 3500000 xmalloc.c 97" \
- "S" "3500000" "3500000"
-ok_xmalloc "strndup custom" 1 "strndup 3500000 xmalloc.c 124" \
- "N" "3500000" "3500000"
-ok_xmalloc "calloc custom" 1 "calloc 3500000 xmalloc.c 148" \
- "C" "3500000" "3500000"
-ok_xmalloc "asprintf custom" 1 "asprintf 3500000 xmalloc.c 172" \
- "A" "3500000" "3500000"
-ok_xmalloc "vasprintf custom" 1 "vasprintf 3500000 xmalloc.c 192" \
- "V" "3500000" "3500000"
+ok_xmalloc "malloc custom" 1 "malloc 5500000 xmalloc.c 38" \
+ "M" "5500000" "5500000"
+ok_xmalloc "realloc custom" 1 "realloc 5500000 xmalloc.c 66" \
+ "R" "5500000" "5500000"
+ok_xmalloc "strdup custom" 1 "strdup 5500000 xmalloc.c 97" \
+ "S" "5500000" "5500000"
+ok_xmalloc "strndup custom" 1 "strndup 5500000 xmalloc.c 143" \
+ "N" "5500000" "5500000"
+ok_xmalloc "calloc custom" 1 "calloc 5500000 xmalloc.c 167" \
+ "C" "5500000" "5500000"
+ok_xmalloc "asprintf custom" 1 "asprintf 5500000 xmalloc.c 191" \
+ "A" "5500000" "5500000"
+ok_xmalloc "vasprintf custom" 1 "vasprintf 5500000 xmalloc.c 210" \
+ "V" "5500000" "5500000"
# Check the smaller ones again just for grins.
-ok_xmalloc "malloc retry" 0 "" "m" "21" "3500000"
-ok_xmalloc "realloc retry" 0 "" "r" "32" "3500000"
-ok_xmalloc "strdup retry" 0 "" "s" "64" "3500000"
-ok_xmalloc "strndup retry" 0 "" "n" "20" "3500000"
-ok_xmalloc "calloc retry" 0 "" "c" "24" "3500000"
-ok_xmalloc "asprintf retry" 0 "" "a" "30" "3500000"
-ok_xmalloc "vasprintf retry" 0 "" "v" "35" "3500000"
+ok_xmalloc "malloc retry" 0 "" "m" "21" "5500000"
+ok_xmalloc "realloc retry" 0 "" "r" "32" "5500000"
+ok_xmalloc "strdup retry" 0 "" "s" "64" "5500000"
+ok_xmalloc "strndup retry" 0 "" "n" "20" "5500000"
+ok_xmalloc "calloc retry" 0 "" "c" "24" "5500000"
+ok_xmalloc "asprintf retry" 0 "" "a" "30" "5500000"
+ok_xmalloc "vasprintf retry" 0 "" "v" "35" "5500000"
diff --git a/tests/util/xmalloc.c b/tests/util/xmalloc.c
index c37396e..394cab5 100644
--- a/tests/util/xmalloc.c
+++ b/tests/util/xmalloc.c
@@ -1,13 +1,30 @@
/*
* Test suite for xmalloc and family.
*
- * Copyright 2008 Board of Trustees, Leland Stanford Jr. University
- * Copyright 2004, 2005, 2006
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- * 2003 by The Internet Software Consortium and Rich Salz
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
*
- * See LICENSE for licensing terms.
+ * Copyright 2000, 2001, 2006 Russ Allbery <rra@stanford.edu>
+ * Copyright 2008, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#line 1 "xmalloc.c"
@@ -62,9 +79,9 @@ test_malloc(size_t size)
/*
- * Allocate half the memory given, write to it, then reallocate to the desired
- * size, writing to the rest and then checking it all. Returns true on
- * success, false on any failure.
+ * Allocate 10 bytes of memory given, write to it, then reallocate to the
+ * desired size, writing to the rest and then checking it all. Returns true
+ * on success, false on any failure.
*/
static int
test_realloc(size_t size)
@@ -119,15 +136,34 @@ test_strdup(size_t size)
/*
* Generate a string of the size indicated plus some, call xstrndup on it, and
- * then ensure the result matches. Returns true on success, false on any
- * failure.
+ * then ensure the result matches. Also test xstrdup on a string that's
+ * shorter than the specified size and ensure that we don't copy too much, and
+ * on a string that's not nul-terminated. Returns true on success, false on
+ * any failure.
*/
static int
test_strndup(size_t size)
{
char *string, *copy;
- int match, toomuch;
+ int shortmatch, nonulmatch, match, toomuch;
+
+ /* Copy a short string. */
+ string = xmalloc(5);
+ memcpy(string, "test", 5);
+ copy = xstrndup(string, size);
+ shortmatch = strcmp(string, copy);
+ free(string);
+ free(copy);
+ /* Copy a string that's not nul-terminated. */
+ string = xmalloc(4);
+ memcpy(string, "test", 4);
+ copy = xstrndup(string, 4);
+ nonulmatch = strcmp(copy, "test");
+ free(string);
+ free(copy);
+
+ /* Now the test of running out of memory. */
string = xmalloc(size + 1);
if (string == NULL)
return 0;
@@ -141,7 +177,7 @@ test_strndup(size_t size)
toomuch = strcmp(string, copy);
free(string);
free(copy);
- return (match == 0 && toomuch != 0);
+ return (shortmatch == 0 && nonulmatch == 0 && match == 0 && toomuch != 0);
}
@@ -195,16 +231,14 @@ test_asprintf(size_t size)
/* Wrapper around vasprintf to do the va_list stuff. */
-static int
+static void
xvasprintf_wrapper(char **strp, const char *format, ...)
{
va_list args;
- int status;
va_start(args, format);
- status = xvasprintf(strp, format, args);
+ xvasprintf(strp, format, args);
va_end(args);
- return status;
}
@@ -298,8 +332,8 @@ main(int argc, char *argv[])
if (size < limit || code == 'r') {
tmp = malloc(code == 'r' ? 10 : size);
if (tmp == NULL) {
- syswarn("Can't allocate initial memory of %lu",
- (unsigned long) size);
+ syswarn("Can't allocate initial memory of %lu (limit %lu)",
+ (unsigned long) size, (unsigned long) limit);
exit(2);
}
free(tmp);
diff --git a/util/macros.h b/util/macros.h
index 0104d9f..54faee5 100644
--- a/util/macros.h
+++ b/util/macros.h
@@ -1,8 +1,18 @@
/*
* Some standard helpful macros.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
- * This work is hereby placed in the public domain by its author.
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
*/
#ifndef UTIL_MACROS_H
@@ -10,6 +20,15 @@
#include <portable/macros.h>
+/*
+ * Used for iterating through arrays. ARRAY_SIZE returns the number of
+ * elements in the array (useful for a < upper bound in a for loop) and
+ * ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
+ * legal to refer to such a pointer as long as it's never dereferenced).
+ */
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#define ARRAY_END(array) (&(array)[ARRAY_SIZE(array)])
+
/* Used for unused parameters to silence gcc warnings. */
#define UNUSED __attribute__((__unused__))
diff --git a/util/messages-krb5.c b/util/messages-krb5.c
index 7f35d29..23fd56a 100644
--- a/util/messages-krb5.c
+++ b/util/messages-krb5.c
@@ -1,15 +1,34 @@
/*
- * Error handling for Kerberos v5.
+ * Error handling for Kerberos.
*
* Provides versions of die and warn that take a Kerberos context and a
* Kerberos error code and append the Kerberos error message to the provided
* formatted message.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
* Copyright 2006, 2007, 2008, 2009, 2010
- * Board of Trustees, Leland Stanford Jr. University
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * See LICENSE for licensing terms.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
@@ -32,12 +51,15 @@ die_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
char *message;
va_list args;
- k5_msg = krb5_get_error_message(ctx, code);
+ if (ctx != NULL)
+ k5_msg = krb5_get_error_message(ctx, code);
va_start(args, format);
- if (xvasprintf(&message, format, args) < 0)
- die("internal error: unable to format error message");
+ xvasprintf(&message, format, args);
va_end(args);
- die("%s: %s", message, k5_msg);
+ if (k5_msg == NULL)
+ die("%s", message);
+ else
+ die("%s: %s", message, k5_msg);
}
@@ -51,12 +73,16 @@ warn_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
char *message;
va_list args;
- k5_msg = krb5_get_error_message(ctx, code);
+ if (ctx != NULL)
+ k5_msg = krb5_get_error_message(ctx, code);
va_start(args, format);
- if (xvasprintf(&message, format, args) < 0)
- die("internal error: unable to format error message");
+ xvasprintf(&message, format, args);
va_end(args);
- warn("%s: %s", message, k5_msg);
+ if (k5_msg == NULL)
+ warn("%s", message);
+ else
+ warn("%s: %s", message, k5_msg);
free(message);
- krb5_free_error_message(ctx, k5_msg);
+ if (k5_msg != NULL)
+ krb5_free_error_message(ctx, k5_msg);
}
diff --git a/util/messages-krb5.h b/util/messages-krb5.h
index 3b763c8..a61d7cd 100644
--- a/util/messages-krb5.h
+++ b/util/messages-krb5.h
@@ -1,11 +1,30 @@
/*
* Prototypes for error handling for Kerberos.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
* Copyright 2006, 2007, 2008, 2009, 2010
- * Board of Trustees, Leland Stanford Jr. University
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * See LICENSE for licensing terms.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#ifndef UTIL_MESSAGES_KRB5_H
diff --git a/util/messages.c b/util/messages.c
index 3592692..52fcfb7 100644
--- a/util/messages.c
+++ b/util/messages.c
@@ -50,13 +50,31 @@
* generates given the format and arguments), a format, an argument list as a
* va_list, and the applicable errno value (if any).
*
- * Copyright 2008 Board of Trustees, Leland Stanford Jr. University
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Copyright 2008, 2009, 2010
+ * The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
* 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * This code is derived from software contributed to the Internet Software
+ * Consortium by Rich Salz.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
@@ -189,8 +207,8 @@ message_log_syslog(int pri, size_t len, const char *fmt, va_list args, int err)
buffer = malloc(len + 1);
if (buffer == NULL) {
- fprintf(stderr, "failed to malloc %u bytes at %s line %d: %s",
- len + 1, __FILE__, __LINE__, strerror(errno));
+ fprintf(stderr, "failed to malloc %lu bytes at %s line %d: %s",
+ (unsigned long) len + 1, __FILE__, __LINE__, strerror(errno));
exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);
}
vsnprintf(buffer, len + 1, fmt, args);
diff --git a/util/messages.h b/util/messages.h
index dbdb256..463137c 100644
--- a/util/messages.h
+++ b/util/messages.h
@@ -1,13 +1,30 @@
/*
* Prototypes for message and error reporting (possibly fatal).
*
- * Copyright 2008, 2010 Board of Trustees, Leland Stanford Jr. University
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2008, 2010
+ * The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
* 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * This code is derived from software contributed to the Internet Software
+ * Consortium by Rich Salz.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef UTIL_MESSAGES_H
@@ -60,21 +77,21 @@ void message_handlers_die(unsigned int count, ...);
* argument list, and the errno setting if any.
*/
void message_log_stdout(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_stderr(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_syslog_debug(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_syslog_info(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_syslog_notice(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_syslog_warning(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_syslog_err(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
void message_log_syslog_crit(size_t, const char *, va_list, int)
- __attribute((__nonnull__));
+ __attribute__((__nonnull__));
/* The type of a message handler. */
typedef void (*message_handler_func)(size_t, const char *, va_list, int);
diff --git a/util/xmalloc.c b/util/xmalloc.c
index 4e05f96..a78e31a 100644
--- a/util/xmalloc.c
+++ b/util/xmalloc.c
@@ -55,12 +55,30 @@
* header file defines macros named xmalloc, etc. that pass the file name and
* line number to these functions.
*
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2012
+ * The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
* 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * This code is derived from software contributed to the Internet Software
+ * Consortium by Rich Salz.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
@@ -149,23 +167,34 @@ x_strdup(const char *s, const char *file, int line)
}
+/*
+ * Avoid using the system strndup function since it may not exist (on Mac OS
+ * X, for example), and there's no need to introduce another portability
+ * requirement.
+ */
char *
x_strndup(const char *s, size_t size, const char *file, int line)
{
- char *p;
+ const char *p;
+ size_t length;
+ char *copy;
- p = malloc(size + 1);
- while (p == NULL) {
- (*xmalloc_error_handler)("strndup", size + 1, file, line);
- p = malloc(size + 1);
+ /* Don't assume that the source string is nul-terminated. */
+ for (p = s; (size_t) (p - s) < size && *p != '\0'; p++)
+ ;
+ length = p - s;
+ copy = malloc(length + 1);
+ while (copy == NULL) {
+ (*xmalloc_error_handler)("strndup", length + 1, file, line);
+ copy = malloc(length + 1);
}
- memcpy(p, s, size);
- p[size] = '\0';
- return p;
+ memcpy(copy, s, length);
+ copy[length] = '\0';
+ return copy;
}
-int
+void
x_vasprintf(char **strp, const char *fmt, va_list args, const char *file,
int line)
{
@@ -175,7 +204,7 @@ x_vasprintf(char **strp, const char *fmt, va_list args, const char *file,
va_copy(args_copy, args);
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
- while (status < 0 && errno == ENOMEM) {
+ while (status < 0) {
va_copy(args_copy, args);
status = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
@@ -184,12 +213,11 @@ x_vasprintf(char **strp, const char *fmt, va_list args, const char *file,
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
}
- return status;
}
#if HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS
-int
+void
x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
{
va_list args, args_copy;
@@ -199,7 +227,7 @@ x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
va_copy(args_copy, args);
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
- while (status < 0 && errno == ENOMEM) {
+ while (status < 0) {
va_copy(args_copy, args);
status = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
@@ -208,10 +236,9 @@ x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
}
- return status;
}
#else /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */
-int
+void
x_asprintf(char **strp, const char *fmt, ...)
{
va_list args, args_copy;
@@ -221,7 +248,7 @@ x_asprintf(char **strp, const char *fmt, ...)
va_copy(args_copy, args);
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
- while (status < 0 && errno == ENOMEM) {
+ while (status < 0) {
va_copy(args_copy, args);
status = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
@@ -230,6 +257,5 @@ x_asprintf(char **strp, const char *fmt, ...)
status = vasprintf(strp, fmt, args_copy);
va_end(args_copy);
}
- return status;
}
#endif /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */
diff --git a/util/xmalloc.h b/util/xmalloc.h
index 657a6bb..55a0b91 100644
--- a/util/xmalloc.h
+++ b/util/xmalloc.h
@@ -1,13 +1,30 @@
/*
* Prototypes for malloc routines with failure handling.
*
- * Copyright 2010 Board of Trustees, Leland Stanford Jr. University
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Copyright 2010, 2012
+ * The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
* 2002, 2003 by The Internet Software Consortium and Rich Salz
*
- * See LICENSE for licensing terms.
+ * This code is derived from software contributed to the Internet Software
+ * Consortium by Rich Salz.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef UTIL_XMALLOC_H
@@ -67,15 +84,15 @@ char *x_strdup(const char *, const char *, int)
__attribute__((__malloc__, __nonnull__));
char *x_strndup(const char *, size_t, const char *, int)
__attribute__((__malloc__, __nonnull__));
-int x_vasprintf(char **, const char *, va_list, const char *, int)
+void x_vasprintf(char **, const char *, va_list, const char *, int)
__attribute__((__nonnull__));
/* asprintf special case. */
#if HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS
-int x_asprintf(char **, const char *, int, const char *, ...)
+void x_asprintf(char **, const char *, int, const char *, ...)
__attribute__((__nonnull__, __format__(printf, 4, 5)));
#else
-int x_asprintf(char **, const char *, ...)
+void x_asprintf(char **, const char *, ...)
__attribute__((__nonnull__, __format__(printf, 2, 3)));
#endif