summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.w322
-rw-r--r--NEWS13
-rw-r--r--README15
-rw-r--r--client/open.c2
-rw-r--r--configure.ac9
-rw-r--r--m4/gssapi.m457
-rw-r--r--m4/inet-ntoa.m43
-rw-r--r--m4/ld-version.m43
-rw-r--r--m4/lib-depends.m43
-rw-r--r--m4/lib-pathname.m43
-rw-r--r--m4/pcre.m43
-rw-r--r--m4/snprintf.m43
-rw-r--r--m4/socket.m43
-rw-r--r--m4/vamacros.m43
-rw-r--r--portable/asprintf.c3
-rw-r--r--portable/daemon.c3
-rw-r--r--portable/dummy.c3
-rw-r--r--portable/getaddrinfo.c64
-rw-r--r--portable/getaddrinfo.h3
-rw-r--r--portable/getnameinfo.c9
-rw-r--r--portable/getnameinfo.h12
-rw-r--r--portable/getopt.c3
-rw-r--r--portable/getopt.h14
-rw-r--r--portable/gssapi-mech.c17
-rw-r--r--portable/gssapi.h13
-rw-r--r--portable/inet_aton.c3
-rw-r--r--portable/inet_ntoa.c3
-rw-r--r--portable/inet_ntop.c3
-rw-r--r--portable/macros.h3
-rw-r--r--portable/setenv.c3
-rw-r--r--portable/snprintf.c3
-rw-r--r--portable/socket.h186
-rw-r--r--portable/stdbool.h3
-rw-r--r--portable/strlcat.c3
-rw-r--r--portable/strlcpy.c3
-rw-r--r--portable/system.h66
-rw-r--r--portable/uio.h3
-rw-r--r--portable/winsock.c3
-rw-r--r--tests/portable/asprintf-t.c3
-rw-r--r--tests/portable/daemon-t.c3
-rw-r--r--tests/portable/getaddrinfo-t.c11
-rw-r--r--tests/portable/getnameinfo-t.c3
-rw-r--r--tests/portable/getopt-t.c3
-rw-r--r--tests/portable/inet_aton-t.c3
-rw-r--r--tests/portable/inet_ntoa-t.c3
-rw-r--r--tests/portable/inet_ntop-t.c3
-rw-r--r--tests/portable/setenv-t.c3
-rw-r--r--tests/portable/snprintf-t.c3
-rw-r--r--tests/portable/strlcat-t.c3
-rw-r--r--tests/portable/strlcpy-t.c3
-rw-r--r--tests/tap/kerberos.sh3
-rw-r--r--tests/tap/messages.c3
-rw-r--r--tests/tap/messages.h3
-rw-r--r--tests/tap/process.c96
-rw-r--r--tests/tap/process.h24
-rw-r--r--tests/tap/remctl.h3
-rw-r--r--tests/tap/remctl.sh3
-rw-r--r--tests/util/concat-t.c3
-rw-r--r--tests/util/fakewrite.c3
-rw-r--r--tests/util/fdflag-t.c3
-rw-r--r--tests/util/messages-t.c95
-rw-r--r--tests/util/network-t.c160
-rw-r--r--tests/util/vector-t.c3
-rwxr-xr-xtests/util/xmalloc-t3
-rw-r--r--tests/util/xmalloc.c9
-rw-r--r--tests/util/xwrite-t.c3
-rw-r--r--util/concat.c3
-rw-r--r--util/concat.h3
-rw-r--r--util/fdflag.c67
-rw-r--r--util/fdflag.h16
-rw-r--r--util/macros.h12
-rw-r--r--util/messages.c7
-rw-r--r--util/messages.h5
-rw-r--r--util/network.c118
-rw-r--r--util/network.h13
-rw-r--r--util/vector.c11
-rw-r--r--util/vector.h7
-rw-r--r--util/xmalloc.c3
-rw-r--r--util/xmalloc.h3
-rw-r--r--util/xwrite.c3
-rw-r--r--util/xwrite.h3
81 files changed, 952 insertions, 334 deletions
diff --git a/Makefile.w32 b/Makefile.w32
index 1117ce7..ffa9b9a 100644
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -15,7 +15,7 @@ remctl.exe: remctl.obj getopt.obj messages.obj asprintf.obj winsock.obj xmalloc.
remctl.lib: remctl.dll
-remctl.dll: api.obj client-v1.obj client-v2.obj error.obj open.obj network.obj asprintf.obj concat.obj gss-tokens.obj gss-errors.obj inet_aton.obj inet_ntop.obj strlcpy.obj strlcat.obj tokens.obj messages.obj winsock.obj xmalloc.obj libremctl.res
+remctl.dll: api.obj client-v1.obj client-v2.obj error.obj open.obj network.obj fdflag.obj asprintf.obj concat.obj gss-tokens.obj gss-errors.obj inet_aton.obj inet_ntop.obj strlcpy.obj strlcat.obj tokens.obj messages.obj winsock.obj xmalloc.obj libremctl.res
link $(ldebug) $(lflags) /LIBPATH:"$(KRB5SDK)"\lib\$(CPU) /dll /out:$@ /export:remctl /export:remctl_new /export:remctl_open /export:remctl_close /export:remctl_command /export:remctl_commandv /export:remctl_error /export:remctl_output $** $(GSSAPI_LIB) ws2_32.lib advapi32.lib
{client\}.c{}.obj::
diff --git a/NEWS b/NEWS
index c8b0f92..29cfb44 100644
--- a/NEWS
+++ b/NEWS
@@ -22,10 +22,23 @@ remctl 2.19 (unreleased)
but the documentation said this was not allowed. Fix the
documentation to match the implementation.
+ Use PATH_KRB5_CONFIG as the environment variable to set the path to
+ krb5-config rather than KRB5_CONFIG when running configure, since the
+ latter is used by the Kerberos libraries to specify an alternative
+ path to krb5.conf.
+
Update to rra-c-util 3.9:
+ * Prefer gssapi/gssapi.h to gssapi.h.
+ * Include strings.h if it exists for strncasecmp on some platforms.
+ * getaddrinfo replacement now portable to systems with bad netdb.h.
+ * Avoid krb5-config if --with-gssapi-{include,lib} are given.
+ * Add Windows implementation of fdflag_nonblocking.
+ * The network_connect utility functions now take an optional timeout.
* Wait longer for remctld to start in remctl tests.
* Use an atexit handler to clean up after Kerberos tests.
+ * Use typedef instead of #define for socklen_t and sig_atomic_t.
+ * Stop providing or using INADDR_LOOPBACK for portability reasons.
Update to C TAP Harness 1.8:
diff --git a/README b/README
index c4b2441..c4994af 100644
--- a/README
+++ b/README
@@ -187,18 +187,21 @@ INSTALLATION (UNIX)
You can also individually set the paths to the include directory and the
library directory with --with-gssapi-include and --with-gssapi-lib. You
may need to do this if Autoconf can't figure out whether to use lib,
- lib32, or lib64 on your platform. Note that these settings aren't used
- if a krb5-config script is found.
+ lib32, or lib64 on your platform.
To specify a particular krb5-config script to use, either set the
- KRB5_CONFIG environment variable or pass it to configure like:
+ PATH_KRB5_CONFIG environment variable or pass it to configure like:
- ./configure KRB5_CONFIG=/path/to/krb5-config
+ ./configure PATH_KRB5_CONFIG=/path/to/krb5-config
To not use krb5-config and force library probing even if there is a
- krb5-config script on your path, set KRB5_CONFIG to a nonexistent path:
+ krb5-config script on your path, set PATH_KRB5_CONFIG to a nonexistent
+ path:
- ./configure KRB5_CONFIG=/nonexistent
+ ./configure PATH_KRB5_CONFIG=/nonexistent
+
+ krb5-config is not used and library probing is always done if either
+ --with-gssapi-include or --with-gssapi-lib are given.
remctl will automatically build with PCRE support if pcre-config or the
PCRE library are found. You can pass --with-pcre to configure to
diff --git a/client/open.c b/client/open.c
index 725cd00..9acd0a1 100644
--- a/client/open.c
+++ b/client/open.c
@@ -56,7 +56,7 @@ internal_connect(struct remctl *r, const char *host, unsigned short port)
gai_strerror(status));
return INVALID_SOCKET;
}
- fd = network_connect(ai, r->source);
+ fd = network_connect(ai, r->source, 0);
freeaddrinfo(ai);
if (fd == INVALID_SOCKET) {
internal_set_error(r, "cannot connect to %s (port %hu): %s", host,
diff --git a/configure.ac b/configure.ac
index f949261..96e55a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,6 +29,7 @@ RRA_LIB_GSSAPI
AC_HEADER_STDBOOL
AC_CHECK_HEADERS([sys/bitypes.h sys/filio.h sys/select.h sys/uio.h syslog.h])
AC_CHECK_DECLS([snprintf, vsnprintf])
+AC_CHECK_DECLS([h_errno], [], [], [#include <netdb.h>])
AC_CHECK_DECLS([inet_aton, inet_ntoa], [], [],
[#include <sys/types.h>
#include <netinet/in.h>
@@ -39,14 +40,10 @@ AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [],
[#include <sys/types.h>
#include <sys/socket.h>])
AC_TYPE_LONG_LONG_INT
-AC_CHECK_TYPE([sig_atomic_t], [],
- [AC_DEFINE([sig_atomic_t], [int],
- [Define to int if <signal.h> does not define.])],
+AC_CHECK_TYPES([sig_atomic_t], [], [],
[#include <sys/types.h>
#include <signal.h>])
-AC_CHECK_TYPE([socklen_t], ,
- [AC_DEFINE([socklen_t], [int],
- [Define to int if <sys/socket.h> does not define.])],
+AC_CHECK_TYPES([socklen_t], [], [],
[#include <sys/types.h>
#include <sys/socket.h>])
AC_CHECK_TYPES([struct sockaddr_in6],
diff --git a/m4/gssapi.m4 b/m4/gssapi.m4
index 6c8c9b6..deaa432 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
@@ -13,6 +14,9 @@ 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
+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, 2011
dnl The Board of Trustees of the Leland Stanford Junior University
@@ -118,6 +122,30 @@ 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],
+[AC_ARG_VAR([PATH_KRB5_CONFIG], [Path to krb5-config])
+ AS_IF([test x"$rra_gssapi_root" != x && test -z "$PATH_KRB5_CONFIG"],
+ [AS_IF([test -x "${rra_gssapi_root}/bin/krb5-config"],
+ [PATH_KRB5_CONFIG="${rra_gssapi_root}/bin/krb5-config"])],
+ [AC_PATH_PROG([PATH_KRB5_CONFIG], [krb5-config], [],
+ [${PATH}:/usr/kerberos/bin])])
+ AS_IF([test x"$PATH_KRB5_CONFIG" != x && test -x "$PATH_KRB5_CONFIG"],
+ [AC_CACHE_CHECK([for gssapi support in krb5-config],
+ [rra_cv_lib_gssapi_config],
+ [AS_IF(["$PATH_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=`"$PATH_KRB5_CONFIG" --cflags gssapi 2>/dev/null`
+ GSSAPI_LIBS=`"$PATH_KRB5_CONFIG" --libs gssapi 2>/dev/null`],
+ [GSSAPI_CPPFLAGS=`"$PATH_KRB5_CONFIG" --cflags 2>/dev/null`
+ GSSAPI_LIBS=`"$PATH_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])])
+
dnl The main macro.
AC_DEFUN([RRA_LIB_GSSAPI],
[AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS])
@@ -150,25 +178,8 @@ 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], [],
- [${PATH}:/usr/kerberos/bin])])
- 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])])])
diff --git a/m4/inet-ntoa.m4 b/m4/inet-ntoa.m4
index 5e68d9c..6cf46d3 100644
--- a/m4/inet-ntoa.m4
+++ b/m4/inet-ntoa.m4
@@ -6,6 +6,9 @@ dnl may still not function with gcc on some platforms (such as IRIX).
dnl Provides RRA_FUNC_INET_NTOA and defines HAVE_INET_NTOA if inet_ntoa is
dnl present and working.
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 Copyright 1999, 2000, 2001, 2003 Russ Allbery <rra@stanford.edu>
dnl Copyright 2008, 2009
dnl The Board of Trustees of the Leland Stanford Junior University
diff --git a/m4/ld-version.m4 b/m4/ld-version.m4
index 97b731d..03d2436 100644
--- a/m4/ld-version.m4
+++ b/m4/ld-version.m4
@@ -4,6 +4,9 @@ dnl Probes whether the linker supports --version-script with a simple version
dnl script that only defines a single version. Sets the Automake conditional
dnl HAVE_LD_VERSION_SCRIPT based on whether it is supported.
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 Based on the gnulib ld-version-script macro from Simon Josefsson
dnl Copyright 2010
diff --git a/m4/lib-depends.m4 b/m4/lib-depends.m4
index 0aa0d1e..b5185f3 100644
--- a/m4/lib-depends.m4
+++ b/m4/lib-depends.m4
@@ -9,6 +9,9 @@ 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 The Board of Trustees of the Leland Stanford Junior University
diff --git a/m4/lib-pathname.m4 b/m4/lib-pathname.m4
index a639b17..fd5a5a1 100644
--- a/m4/lib-pathname.m4
+++ b/m4/lib-pathname.m4
@@ -12,6 +12,9 @@ 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
dnl The Board of Trustees of the Leland Stanford Junior University
diff --git a/m4/pcre.m4 b/m4/pcre.m4
index ca789cb..dc17d66 100644
--- a/m4/pcre.m4
+++ b/m4/pcre.m4
@@ -15,6 +15,9 @@ dnl variables will be empty.
dnl
dnl Depends on 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 2010
dnl The Board of Trustees of the Leland Stanford Junior University
diff --git a/m4/snprintf.m4 b/m4/snprintf.m4
index 51c9202..cd585ef 100644
--- a/m4/snprintf.m4
+++ b/m4/snprintf.m4
@@ -9,6 +9,9 @@ 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 The Board of Trustees of the Leland Stanford Junior University
diff --git a/m4/socket.m4 b/m4/socket.m4
index 3c9e8dc..338a4a4 100644
--- a/m4/socket.m4
+++ b/m4/socket.m4
@@ -9,6 +9,9 @@ dnl RRA_MACRO_SA_LEN
dnl
dnl They use a separate internal source macro to make the code easier to read.
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 Copyright 2008, 2009, 2011
dnl The Board of Trustees of the Leland Stanford Junior University
dnl Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009
diff --git a/m4/vamacros.m4 b/m4/vamacros.m4
index 62cf28f..af98f6a 100644
--- a/m4/vamacros.m4
+++ b/m4/vamacros.m4
@@ -13,6 +13,9 @@ 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 The Board of Trustees of the Leland Stanford Junior University
diff --git a/portable/asprintf.c b/portable/asprintf.c
index d085b64..0093070 100644
--- a/portable/asprintf.c
+++ b/portable/asprintf.c
@@ -4,6 +4,9 @@
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/daemon.c b/portable/daemon.c
index 8e614e3..1a3e25f 100644
--- a/portable/daemon.c
+++ b/portable/daemon.c
@@ -4,6 +4,9 @@
* Provides the same functionality as the library function daemon 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/dummy.c b/portable/dummy.c
index 94333a6..50052ec 100644
--- a/portable/dummy.c
+++ b/portable/dummy.c
@@ -5,6 +5,9 @@
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/getaddrinfo.c b/portable/getaddrinfo.c
index a0f6ad3..2a5d430 100644
--- a/portable/getaddrinfo.c
+++ b/portable/getaddrinfo.c
@@ -16,6 +16,9 @@
* needed to date. Adding IPv6 support isn't worth it; systems with IPv6
* support should already support getaddrinfo natively.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -33,6 +36,26 @@
#include <errno.h>
+/* We need access to h_errno to map errors from gethostbyname. */
+#if !HAVE_DECL_H_ERRNO
+extern int h_errno;
+#endif
+
+/*
+ * The netdb constants, which aren't always defined (particularly if h_errno
+ * isn't declared). We also make sure that a few of the less-used ones are
+ * defined so that we can deal with them in case statements.
+ */
+#ifndef HOST_NOT_FOUND
+# define HOST_NOT_FOUND 1
+# define TRY_AGAIN 2
+# define NO_RECOVERY 3
+# define NO_DATA 4
+#endif
+#ifndef NETDB_INTERNAL
+# define NETDB_INTERNAL -1
+#endif
+
/*
* If we're running the test suite, rename the functions to avoid conflicts
* with the system version. Note that we don't rename the structures and
@@ -46,11 +69,13 @@ const char *test_gai_strerror(int);
void test_freeaddrinfo(struct addrinfo *);
int test_getaddrinfo(const char *, const char *, const struct addrinfo *,
struct addrinfo **);
+#endif
/*
* If the native platform doesn't support AI_NUMERICSERV or AI_NUMERICHOST,
* pick some other values for them.
*/
+#if TESTING
# if AI_NUMERICSERV == 0
# undef AI_NUMERICSERV
# define AI_NUMERICSERV 0x0080
@@ -61,20 +86,6 @@ int test_getaddrinfo(const char *, const char *, const struct addrinfo *,
# endif
#endif
-/* Table of strings corresponding to the EAI_* error codes. */
-static const char * const gai_errors[] = {
- "Host name lookup failure", /* 1 EAI_AGAIN */
- "Invalid flag value", /* 2 EAI_BADFLAGS */
- "Unknown server error", /* 3 EAI_FAIL */
- "Unsupported address family", /* 4 EAI_FAMILY */
- "Memory allocation failure", /* 5 EAI_MEMORY */
- "Host unknown or not given", /* 6 EAI_NONAME */
- "Service not supported for socket", /* 7 EAI_SERVICE */
- "Unsupported socket type", /* 8 EAI_SOCKTYPE */
- "System error", /* 9 EAI_SYSTEM */
- "Supplied buffer too small", /* 10 EAI_OVERFLOW */
-};
-
/*
* Value representing all of the hint flags set. Linux uses flags up to
* 0x0400, so be sure not to break when testing on that platform.
@@ -89,18 +100,32 @@ static const char * const gai_errors[] = {
# define AI_INTERNAL_ALL 0x007f
#endif
+/* Table of strings corresponding to the EAI_* error codes. */
+static const char * const gai_errors[] = {
+ "Host name lookup failure", /* 1 EAI_AGAIN */
+ "Invalid flag value", /* 2 EAI_BADFLAGS */
+ "Unknown server error", /* 3 EAI_FAIL */
+ "Unsupported address family", /* 4 EAI_FAMILY */
+ "Memory allocation failure", /* 5 EAI_MEMORY */
+ "Host unknown or not given", /* 6 EAI_NONAME */
+ "Service not supported for socket", /* 7 EAI_SERVICE */
+ "Unsupported socket type", /* 8 EAI_SOCKTYPE */
+ "System error", /* 9 EAI_SYSTEM */
+ "Supplied buffer too small", /* 10 EAI_OVERFLOW */
+};
+
/* Macro to set the len attribute of sockaddr_in. */
#if HAVE_STRUCT_SOCKADDR_SA_LEN
-# define sin_set_length(s) ((s)->sin_len = sizeof(struct sockaddr_in))
+# define sin_set_length(s) ((s)->sin_len = sizeof(struct sockaddr_in))
#else
-# define sin_set_length(s) /* empty */
+# define sin_set_length(s) /* empty */
#endif
/*
* Used for iterating through arrays. ARRAY_SIZE returns the number of
* elements in the array (useful for a < upper bound in a for loop).
*/
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
/*
@@ -378,7 +403,10 @@ getaddrinfo(const char *nodename, const char *servname,
else {
if (servname == NULL)
return EAI_NONAME;
- addr.s_addr = (flags & AI_PASSIVE) ? INADDR_ANY : INADDR_LOOPBACK;
+ if ((flags & AI_PASSIVE) == AI_PASSIVE)
+ addr.s_addr = INADDR_ANY;
+ else
+ addr.s_addr = htonl(0x7f000001UL);
ai = gai_addrinfo_new(socktype, NULL, addr, port);
if (ai == NULL)
return EAI_MEMORY;
diff --git a/portable/getaddrinfo.h b/portable/getaddrinfo.h
index 37e335b..5bd50d1 100644
--- a/portable/getaddrinfo.h
+++ b/portable/getaddrinfo.h
@@ -9,6 +9,9 @@
* This file should generally be included by way of portable/socket.h rather
* than directly.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/getnameinfo.c b/portable/getnameinfo.c
index bc422ae..8e06611 100644
--- a/portable/getnameinfo.c
+++ b/portable/getnameinfo.c
@@ -13,6 +13,9 @@
* needed so far. Adding IPv6 support isn't worth it; systems with IPv6
* support should already support getnameinfo natively.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -60,7 +63,7 @@ try_name(const char *name, char *node, socklen_t nodelen, int *status)
{
if (strchr(name, '.') == NULL)
return 0;
- if (strlen(name) > nodelen - 1)
+ if (strlen(name) + 1 > (size_t) nodelen)
*status = EAI_OVERFLOW;
else {
strlcpy(node, name, nodelen);
@@ -108,7 +111,7 @@ lookup_name(const struct in_addr *addr, char *node, socklen_t nodelen,
/* Just convert the address to ASCII. */
name = inet_ntoa(*addr);
- if (strlen(name) > nodelen - 1)
+ if (strlen(name) + 1 > (size_t) nodelen)
return EAI_OVERFLOW;
strlcpy(node, name, nodelen);
return 0;
@@ -131,7 +134,7 @@ lookup_service(unsigned short port, char *service, socklen_t servicelen,
protocol = (flags & NI_DGRAM) ? "udp" : "tcp";
srv = getservbyport(htons(port), protocol);
if (srv != NULL) {
- if (strlen(srv->s_name) > servicelen - 1)
+ if (strlen(srv->s_name) + 1 > (size_t) servicelen)
return EAI_OVERFLOW;
strlcpy(service, srv->s_name, servicelen);
return 0;
diff --git a/portable/getnameinfo.h b/portable/getnameinfo.h
index 3e71b8d..c6f8dd0 100644
--- a/portable/getnameinfo.h
+++ b/portable/getnameinfo.h
@@ -8,6 +8,9 @@
* This file should generally be included by way of portable/socket.h rather
* than directly.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -53,11 +56,16 @@
BEGIN_DECLS
+/* Default to a hidden visibility for all portability functions. */
+#pragma GCC visibility push(hidden)
+
/* Function prototypes. */
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *node, socklen_t nodelen,
- char *service, socklen_t servicelen, int flags)
- __attribute__((__visibility__("hidden")));
+ char *service, socklen_t servicelen, int flags);
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
END_DECLS
diff --git a/portable/getopt.c b/portable/getopt.c
index 0ff49ca..06350ab 100644
--- a/portable/getopt.c
+++ b/portable/getopt.c
@@ -6,6 +6,9 @@
* since remctl doesn't use GNU long options, and the code has been rearranged
* and reworked somewhat to fit with my coding style.
*
+ * 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 1997, 2000, 2001, 2002 Benjamin Sittler
* Copyright 2008 Russ Allbery <rra@stanford.edu>
*
diff --git a/portable/getopt.h b/portable/getopt.h
index 160ff6f..d3b6f85 100644
--- a/portable/getopt.h
+++ b/portable/getopt.h
@@ -6,6 +6,9 @@
* since remctl doesn't use GNU long options, and the code has been rearranged
* and reworked somewhat to fit with my coding style.
*
+ * 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 1997, 2000, 2001, 2002 Benjamin Sittler
* Copyright 2008 Russ Allbery <rra@stanford.edu>
*
@@ -39,9 +42,8 @@
BEGIN_DECLS
-/* The primary interface. Call repeatedly to return each option. */
-int getopt(int argc, char *argv[], const char *opts)
- __attribute__((__visibility__("hidden")));
+/* Default to a hidden visibility for all portability functions. */
+#pragma GCC visibility push(hidden)
/*
* The current element in the argv array or, if getopt returns -1, the index
@@ -58,6 +60,12 @@ extern int optopt;
/* The argument to an option. */
extern char *optarg;
+/* The primary interface. Call repeatedly to return each option. */
+int getopt(int argc, char *argv[], const char *opts);
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
END_DECLS
#endif /* !HAVE_GETOPT */
diff --git a/portable/gssapi-mech.c b/portable/gssapi-mech.c
index a7facfc..938c94d 100644
--- a/portable/gssapi-mech.c
+++ b/portable/gssapi-mech.c
@@ -1,13 +1,26 @@
/*
- * Define the Kerberos v5 GSS-API mechanism OID.
+ * Define the Kerberos GSS-API mechanism OID.
*
- * This short bit of code exposes the Kerberos v5 GSS-API mechanism OID has
+ * This short bit of code exposes the Kerberos GSS-API mechanism OID has
* gss_mech_krb5 on platforms that don't have GSS_KRB5_MECHANISM or
* gss_mech_krb5, such as Solaris 10.
*
* On Solaris 10, we could call gss_str_to_oid to convert "kerberos_v5" to an
* OID or to parse the numeric form of an OID, but this doesn't rely on
* configuration files and is just as portable in practice.
+ *
+ * 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>
+ *
+ * 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 <portable/gssapi.h>
diff --git a/portable/gssapi.h b/portable/gssapi.h
index 533a189..13a326e 100644
--- a/portable/gssapi.h
+++ b/portable/gssapi.h
@@ -4,6 +4,19 @@
* This header tries to encapsulate the differences between the MIT and
* Heimdal GSS-API implementations and the differences between various
* versions.
+ *
+ * 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>
+ *
+ * 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_GSSAPI_H
diff --git a/portable/inet_aton.c b/portable/inet_aton.c
index 2de0a61..0767d20 100644
--- a/portable/inet_aton.c
+++ b/portable/inet_aton.c
@@ -5,6 +5,9 @@
* inet_aton for those platforms that don't have it. inet_aton is
* thread-safe.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/inet_ntoa.c b/portable/inet_ntoa.c
index 68d02c5..dafdd70 100644
--- a/portable/inet_ntoa.c
+++ b/portable/inet_ntoa.c
@@ -6,6 +6,9 @@
* as on IRIX when using gcc to compile). inet_ntoa is not thread-safe since
* it uses static storage (inet_ntop should be used instead when available).
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/inet_ntop.c b/portable/inet_ntop.c
index 4408b39..9724ff8 100644
--- a/portable/inet_ntop.c
+++ b/portable/inet_ntop.c
@@ -7,6 +7,9 @@
* call inet_ntop unconditionally without needing to worry about whether the
* host supports IPv6.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/macros.h b/portable/macros.h
index 78fd495..eed772a 100644
--- a/portable/macros.h
+++ b/portable/macros.h
@@ -1,6 +1,9 @@
/*
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/setenv.c b/portable/setenv.c
index 9a0044f..8a4302c 100644
--- a/portable/setenv.c
+++ b/portable/setenv.c
@@ -4,6 +4,9 @@
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
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/socket.h b/portable/socket.h
index cc15a33..89d3459 100644
--- a/portable/socket.h
+++ b/portable/socket.h
@@ -13,7 +13,10 @@
* Windows. It ensures that inet_aton, inet_ntoa, and inet_ntop are available
* and properly prototyped.
*
- * Copyright 2008, 2009
+ * 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, 2011
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006, 2007
* by Internet Systems Consortium, Inc. ("ISC")
@@ -63,98 +66,45 @@
#include <portable/getaddrinfo.h>
#include <portable/getnameinfo.h>
-BEGIN_DECLS
-
-/*
- * Provide prototypes for inet_aton and inet_ntoa if not prototyped in the
- * system header files since they're occasionally available without proper
- * prototypes.
- */
-#if !HAVE_DECL_INET_ATON
-extern int inet_aton(const char *, struct in_addr *);
-#endif
-#if !HAVE_DECL_INET_NTOA
-extern const char * inet_ntoa(const struct in_addr);
-#endif
-#if !HAVE_INET_NTOP
-# ifdef _WIN32
-extern const char * inet_ntop(int, const void *, char *, int);
-# else
-extern const char * inet_ntop(int, const void *, char *, socklen_t)
- __attribute__((__visibility__("hidden")));
-# endif
-#endif
-
-/*
- * Used for portability to Windows, which requires different functions be
- * called to close sockets, send data to or read from sockets, and get socket
- * errors than the regular functions and variables. Windows also uses SOCKET
- * to store socket descriptors instead of an int.
- *
- * socket_init must be called before socket functions are used and
- * socket_shutdown at the end of the program. socket_init may return failure,
- * but this interface doesn't have a way to retrieve the exact error.
- *
- * socket_close, socket_read, and socket_write must be used instead of the
- * standard functions. On Windows, closesocket must be called instead of
- * close for sockets and recv and send must always be used instead of read and
- * write.
- *
- * When reporting errors from socket functions, use socket_errno and
- * socket_strerror instead of errno and strerror. When setting errno to
- * something for socket errors (to preserve errors through close, for
- * example), use socket_set_errno instead of just assigning to errno.
- *
- * Socket file descriptors must be passed and stored in variables of type
- * socket_type rather than an int. Use INVALID_SOCKET for invalid socket file
- * descriptors rather than -1, and compare to INVALID_SOCKET when testing
- * whether operations succeed.
- */
-#ifdef _WIN32
-int socket_init(void);
-# define socket_shutdown() WSACleanup()
-# define socket_close(fd) closesocket(fd)
-# define socket_read(fd, b, s) recv((fd), (b), (s), 0)
-# define socket_write(fd, b, s) send((fd), (b), (s), 0)
-# define socket_errno WSAGetLastError()
-# define socket_set_errno(e) WSASetLastError(e)
-const char *socket_strerror(int);
-typedef SOCKET socket_type;
-#else
-# define socket_init() 1
-# define socket_shutdown() /* empty */
-# define socket_close(fd) close(fd)
-# define socket_read(fd, b, s) read((fd), (b), (s))
-# define socket_write(fd, b, s) write((fd), (b), (s))
-# define socket_errno errno
-# define socket_set_errno(e) errno = (e)
-# define socket_strerror(e) strerror(e)
-# define INVALID_SOCKET -1
-typedef int socket_type;
-#endif
-
-/* Some systems don't define INADDR_LOOPBACK. */
-#ifndef INADDR_LOOPBACK
-# define INADDR_LOOPBACK 0x7f000001UL
+/* Define socklen_t if it's not available in sys/socket.h. */
+#ifndef HAVE_SOCKLEN_T
+typedef socklen_t int;
#endif
/*
- * Defined by RFC 3493, used to store a generic address. Note that this
- * doesn't do the alignment mangling that RFC 3493 does; it's not clear if
- * that needs be added. However, I've not gotten any complaints yet (probably
- * because nearly everyone now has sockaddr_storage).
+ * Defined by RFC 3493, used to store a generic address. All of the extra
+ * goop here is to ensure that the structs are appropriately aligned on
+ * platforms that may require 64-bit alignment for the embedded addresses.
*/
#if !HAVE_STRUCT_SOCKADDR_STORAGE
+# define SS_MAXSIZE_ 128
+# ifdef HAVE_LONG_LONG_INT
+# define SS_ALIGNSIZE_ sizeof(long long)
+# define SS_ALIGNTYPE_ long long
+# else
+# define SS_ALIGNSIZE_ sizeof(long)
+# define SS_ALIGNTYPE_ long
+# endif
# if HAVE_STRUCT_SOCKADDR_SA_LEN
+# define SS_PAD1SIZE_ (SS_ALIGNSIZE_ - 2 * sizeof(unsigned char))
+# define SS_PAD2SIZE_ \
+ (SS_MAXSIZE_ - (2 * sizeof(unsigned char) + SS_PAD1SIZE_ + SS_ALIGNSIZE_))
struct sockaddr_storage {
unsigned char ss_len;
unsigned char ss_family;
- unsigned char __padding[128 - 2];
+ char __ss_pad1[SS_PAD1SIZE_];
+ SS_ALIGNTYPE_ __ss_align;
+ char __ss_pad2[SS_PAD2SIZE_];
};
# else
+# define SS_PAD1SIZE_ (SS_ALIGNSIZE_ - sizeof(unsigned char))
+# define SS_PAD2SIZE_ \
+ (SS_MAXSIZE_ - (sizeof(unsigned char) + SS_PAD1SIZE_ + SS_ALIGNSIZE_))
struct sockaddr_storage {
unsigned short ss_family;
- unsigned char __padding[128 - 2];
+ char __ss_pad1[SS_PAD1SIZE_];
+ SS_ALIGNTYPE_ __ss_align;
+ char __ss_pad2[SS_PAD2SIZE_];
};
# endif
#endif
@@ -238,6 +188,82 @@ struct sockaddr_storage {
# define EAFNOSUPPORT EDOM
#endif
+BEGIN_DECLS
+
+/*
+ * Provide prototypes for inet_aton and inet_ntoa if not prototyped in the
+ * system header files since they're occasionally available without proper
+ * prototypes.
+ */
+#if !HAVE_DECL_INET_ATON
+extern int inet_aton(const char *, struct in_addr *);
+#endif
+#if !HAVE_DECL_INET_NTOA
+extern const char *inet_ntoa(const struct in_addr);
+#endif
+
+/* Default to a hidden visibility for all portability functions. */
+#pragma GCC visibility push(hidden)
+
+#if !HAVE_INET_NTOP
+# ifdef _WIN32
+extern const char *inet_ntop(int, const void *, char *, int);
+# else
+extern const char *inet_ntop(int, const void *, char *, socklen_t);
+# endif
+#endif
+
+/*
+ * Used for portability to Windows, which requires different functions be
+ * called to close sockets, send data to or read from sockets, and get socket
+ * errors than the regular functions and variables. Windows also uses SOCKET
+ * to store socket descriptors instead of an int.
+ *
+ * socket_init must be called before socket functions are used and
+ * socket_shutdown at the end of the program. socket_init may return failure,
+ * but this interface doesn't have a way to retrieve the exact error.
+ *
+ * socket_close, socket_read, and socket_write must be used instead of the
+ * standard functions. On Windows, closesocket must be called instead of
+ * close for sockets and recv and send must always be used instead of read and
+ * write.
+ *
+ * When reporting errors from socket functions, use socket_errno and
+ * socket_strerror instead of errno and strerror. When setting errno to
+ * something for socket errors (to preserve errors through close, for
+ * example), use socket_set_errno instead of just assigning to errno.
+ *
+ * Socket file descriptors must be passed and stored in variables of type
+ * socket_type rather than an int. Use INVALID_SOCKET for invalid socket file
+ * descriptors rather than -1, and compare to INVALID_SOCKET when testing
+ * whether operations succeed.
+ */
+#ifdef _WIN32
+int socket_init(void);
+# define socket_shutdown() WSACleanup()
+# define socket_close(fd) closesocket(fd)
+# define socket_read(fd, b, s) recv((fd), (b), (s), 0)
+# define socket_write(fd, b, s) send((fd), (b), (s), 0)
+# define socket_errno WSAGetLastError()
+# define socket_set_errno(e) WSASetLastError(e)
+const char *socket_strerror(int);
+typedef SOCKET socket_type;
+#else
+# define socket_init() 1
+# define socket_shutdown() /* empty */
+# define socket_close(fd) close(fd)
+# define socket_read(fd, b, s) read((fd), (b), (s))
+# define socket_write(fd, b, s) write((fd), (b), (s))
+# define socket_errno errno
+# define socket_set_errno(e) errno = (e)
+# define socket_strerror(e) strerror(e)
+# define INVALID_SOCKET -1
+typedef int socket_type;
+#endif
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
END_DECLS
#endif /* !PORTABLE_SOCKET_H */
diff --git a/portable/stdbool.h b/portable/stdbool.h
index 5632f16..6f2fc7e 100644
--- a/portable/stdbool.h
+++ b/portable/stdbool.h
@@ -5,6 +5,9 @@
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/strlcat.c b/portable/strlcat.c
index 69fcb5e..3bee4ee 100644
--- a/portable/strlcat.c
+++ b/portable/strlcat.c
@@ -9,6 +9,9 @@
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/strlcpy.c b/portable/strlcpy.c
index b83c86e..df75fd8 100644
--- a/portable/strlcpy.c
+++ b/portable/strlcpy.c
@@ -8,6 +8,9 @@
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/system.h b/portable/system.h
index 6b04793..1fee43a 100644
--- a/portable/system.h
+++ b/portable/system.h
@@ -13,11 +13,15 @@
* #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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -45,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
@@ -63,6 +70,38 @@
/* Get the bool type. */
#include <portable/stdbool.h>
+/* Windows provides snprintf under a different name. */
+#ifdef _WIN32
+# define snprintf _snprintf
+#endif
+
+/* Define sig_atomic_t if it's not available in signal.h. */
+#ifndef HAVE_SIG_ATOMIC_T
+typedef sig_atomic_t int;
+#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. */
@@ -103,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 e9ef1a8..3bd1f96 100644
--- a/portable/uio.h
+++ b/portable/uio.h
@@ -5,6 +5,9 @@
* (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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/portable/winsock.c b/portable/winsock.c
index 10032ca..fc65463 100644
--- a/portable/winsock.c
+++ b/portable/winsock.c
@@ -4,6 +4,9 @@
* Provides supporting functions and wrappers that help with portability to
* the Windows socket API.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/asprintf-t.c b/tests/portable/asprintf-t.c
index 79cdd76..4513a85 100644
--- a/tests/portable/asprintf-t.c
+++ b/tests/portable/asprintf-t.c
@@ -1,6 +1,9 @@
/*
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/daemon-t.c b/tests/portable/daemon-t.c
index 8451811..9f62732 100644
--- a/tests/portable/daemon-t.c
+++ b/tests/portable/daemon-t.c
@@ -1,6 +1,9 @@
/*
* daemon 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/getaddrinfo-t.c b/tests/portable/getaddrinfo-t.c
index 5f4d157..499f3b4 100644
--- a/tests/portable/getaddrinfo-t.c
+++ b/tests/portable/getaddrinfo-t.c
@@ -1,6 +1,9 @@
/*
* getaddrinfo 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -65,7 +68,7 @@ main(void)
is_int(sizeof(struct sockaddr_in), ai->ai_addrlen, "...right addrlen");
saddr = (struct sockaddr_in *) ai->ai_addr;
is_int(htons(25), saddr->sin_port, "...right port");
- ok(saddr->sin_addr.s_addr == INADDR_LOOPBACK, "...right address");
+ is_int(htonl(0x7f000001UL), saddr->sin_addr.s_addr, "...right address");
test_freeaddrinfo(ai);
memset(&hints, 0, sizeof(hints));
@@ -75,7 +78,7 @@ main(void)
is_int(SOCK_STREAM, ai->ai_socktype, "...right socktype");
saddr = (struct sockaddr_in *) ai->ai_addr;
is_int(htons(25), saddr->sin_port, "...right port");
- ok(saddr->sin_addr.s_addr == INADDR_ANY, "...right address");
+ is_int(INADDR_ANY, saddr->sin_addr.s_addr, "...right address");
test_freeaddrinfo(ai);
service = getservbyname("smtp", "tcp");
@@ -88,7 +91,7 @@ main(void)
is_int(SOCK_STREAM, ai->ai_socktype, "...right socktype");
saddr = (struct sockaddr_in *) ai->ai_addr;
is_int(htons(25), saddr->sin_port, "...right port");
- ok(saddr->sin_addr.s_addr == INADDR_ANY, "...right address");
+ is_int(INADDR_ANY, saddr->sin_addr.s_addr, "...right address");
test_freeaddrinfo(ai);
}
@@ -103,7 +106,7 @@ main(void)
"valid AI_NUMERICSERV");
saddr = (struct sockaddr_in *) ai->ai_addr;
is_int(htons(25), saddr->sin_port, "...right port");
- ok(saddr->sin_addr.s_addr == INADDR_LOOPBACK, "...right address");
+ is_int(htonl(0x7f000001UL), saddr->sin_addr.s_addr, "...right address");
test_freeaddrinfo(ai);
ok(test_getaddrinfo(NULL, NULL, NULL, &ai) == EAI_NONAME, "EAI_NONAME");
diff --git a/tests/portable/getnameinfo-t.c b/tests/portable/getnameinfo-t.c
index b12d4d8..21c0533 100644
--- a/tests/portable/getnameinfo-t.c
+++ b/tests/portable/getnameinfo-t.c
@@ -1,6 +1,9 @@
/*
* getnameinfo 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/getopt-t.c b/tests/portable/getopt-t.c
index c399969..20e9636 100644
--- a/tests/portable/getopt-t.c
+++ b/tests/portable/getopt-t.c
@@ -1,6 +1,9 @@
/*
* getopt 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 2008, 2009
* The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/portable/inet_aton-t.c b/tests/portable/inet_aton-t.c
index 185003a..048eca9 100644
--- a/tests/portable/inet_aton-t.c
+++ b/tests/portable/inet_aton-t.c
@@ -1,6 +1,9 @@
/*
* inet_aton 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/inet_ntoa-t.c b/tests/portable/inet_ntoa-t.c
index 3c1b019..95b9fc0 100644
--- a/tests/portable/inet_ntoa-t.c
+++ b/tests/portable/inet_ntoa-t.c
@@ -1,6 +1,9 @@
/*
* inet_ntoa 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/inet_ntop-t.c b/tests/portable/inet_ntop-t.c
index 8071d36..ee29039 100644
--- a/tests/portable/inet_ntop-t.c
+++ b/tests/portable/inet_ntop-t.c
@@ -1,6 +1,9 @@
/*
* inet_ntop 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/setenv-t.c b/tests/portable/setenv-t.c
index c21a0e2..a1aecb5 100644
--- a/tests/portable/setenv-t.c
+++ b/tests/portable/setenv-t.c
@@ -1,6 +1,9 @@
/*
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/snprintf-t.c b/tests/portable/snprintf-t.c
index 1df0ba8..927de96 100644
--- a/tests/portable/snprintf-t.c
+++ b/tests/portable/snprintf-t.c
@@ -1,6 +1,9 @@
/*
* 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 2000, 2001, 2002, 2003, 2004, 2005, 2006
* Russ Allbery <rra@stanford.edu>
diff --git a/tests/portable/strlcat-t.c b/tests/portable/strlcat-t.c
index 3af91ca..54d0d40 100644
--- a/tests/portable/strlcat-t.c
+++ b/tests/portable/strlcat-t.c
@@ -1,6 +1,9 @@
/*
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/portable/strlcpy-t.c b/tests/portable/strlcpy-t.c
index 54dcbd5..26aa8f2 100644
--- a/tests/portable/strlcpy-t.c
+++ b/tests/portable/strlcpy-t.c
@@ -1,6 +1,9 @@
/*
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/tap/kerberos.sh b/tests/tap/kerberos.sh
index 577598b..2dacc42 100644
--- a/tests/tap/kerberos.sh
+++ b/tests/tap/kerberos.sh
@@ -1,5 +1,8 @@
# Shell function library to initialize Kerberos credentials
#
+# 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
# The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/tap/messages.c b/tests/tap/messages.c
index 9d17c0c..78a1fee 100644
--- a/tests/tap/messages.c
+++ b/tests/tap/messages.c
@@ -5,6 +5,9 @@
* into a buffer that can be inspected later, allowing testing of error
* 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, 2004, 2005 Russ Allbery <rra@stanford.edu>
* Copyright 2006, 2007, 2009
* The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/tap/messages.h b/tests/tap/messages.h
index 8f53aa2..5e59bff 100644
--- a/tests/tap/messages.h
+++ b/tests/tap/messages.h
@@ -1,6 +1,9 @@
/*
* 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
* The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/tap/process.c b/tests/tap/process.c
index be364e4..fc94295 100644
--- a/tests/tap/process.c
+++ b/tests/tap/process.c
@@ -1,14 +1,18 @@
/*
* 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.
+ *
+ * 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, 2005 Russ Allbery <rra@stanford.edu>
- * Copyright 2009, 2010
+ * 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
@@ -37,26 +41,23 @@
#include <tests/tap/basic.h>
#include <tests/tap/process.h>
-#include <util/xmalloc.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);
@@ -76,7 +77,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 {
@@ -86,7 +87,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);
@@ -94,7 +95,7 @@ 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';
@@ -102,9 +103,32 @@ is_function_output(test_function_type function, int status, const char *output,
sysbail("waitpid failed");
}
+ /* 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)
+ if (vasprintf(&msg, format, args) < 0)
bail("cannot format test description");
va_end(args);
ok(WIFEXITED(rval), "%s (exited)", msg);
@@ -113,3 +137,39 @@ 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);
+ }
+}
diff --git a/tests/tap/process.h b/tests/tap/process.h
index 40bdd56..cd4eadc 100644
--- a/tests/tap/process.h
+++ b/tests/tap/process.h
@@ -1,6 +1,9 @@
/*
* Utility functions for tests that use subprocesses.
*
+ * 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
* The Board of Trustees of the Leland Stanford Junior University
@@ -35,16 +38,27 @@ 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.h b/tests/tap/remctl.h
index e7e14ef..eda8d61 100644
--- a/tests/tap/remctl.h
+++ b/tests/tap/remctl.h
@@ -4,6 +4,9 @@
* Provides functions to start and stop a remctl daemon that uses the test
* Kerberos environment and runs on port 14373 instead of the default 4373.
*
+ * 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, 2011
* The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/tap/remctl.sh b/tests/tap/remctl.sh
index afceb8b..07302f3 100644
--- a/tests/tap/remctl.sh
+++ b/tests/tap/remctl.sh
@@ -1,5 +1,8 @@
# Shell function library to start and stop remctld
#
+# 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
# The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/util/concat-t.c b/tests/util/concat-t.c
index 8333c44..384af3a 100644
--- a/tests/util/concat-t.c
+++ b/tests/util/concat-t.c
@@ -1,6 +1,9 @@
/*
* concat 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/util/fakewrite.c b/tests/util/fakewrite.c
index 6c4390b..5f9a056 100644
--- a/tests/util/fakewrite.c
+++ b/tests/util/fakewrite.c
@@ -1,6 +1,9 @@
/*
* Fake write and writev functions for testing xwrite and xwritev.
*
+ * 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 2000, 2001, 2002, 2004 Russ Allbery <rra@stanford.edu>
*
* Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/tests/util/fdflag-t.c b/tests/util/fdflag-t.c
index b7334c1..adc5ebc 100644
--- a/tests/util/fdflag-t.c
+++ b/tests/util/fdflag-t.c
@@ -1,6 +1,9 @@
/*
* fdflag 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 2008, 2009
* The Board of Trustees of the Leland Stanford Junior University
diff --git a/tests/util/messages-t.c b/tests/util/messages-t.c
index bac53d2..aa895fa 100644
--- a/tests/util/messages-t.c
+++ b/tests/util/messages-t.c
@@ -1,9 +1,12 @@
/*
* 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 2002, 2004, 2005 Russ Allbery <rra@stanford.edu>
- * Copyright 2009, 2010
+ * 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
@@ -36,6 +39,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>
@@ -43,24 +47,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");
@@ -68,17 +75,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;
@@ -92,55 +99,55 @@ static void log_msg(int len, const char *format, va_list args, int error) {
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");
@@ -161,7 +168,7 @@ test_strerror(int status, const char *output, int error,
full_output = concat(output, ": ", strerror(error), "\n", (char *) NULL);
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);
}
@@ -178,43 +185,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/network-t.c b/tests/util/network-t.c
index ac8ee8a..3e04b1d 100644
--- a/tests/util/network-t.c
+++ b/tests/util/network-t.c
@@ -1,6 +1,9 @@
/*
* network 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 2005 Russ Allbery <rra@stanford.edu>
* Copyright 2009, 2010, 2011
@@ -88,15 +91,28 @@ listener(socket_type fd)
* A varient version of the server portion of the test. Takes an array of
* sockets and the size of the sockets and accepts a connection on any of
* those sockets.
+ *
+ * saddr is allocated from the heap instead of using a local struct
+ * sockaddr_storage to work around a misdiagnosis of strict aliasing
+ * violations from gcc 4.4 (fixed in later versions).
*/
static void
listener_any(socket_type fds[], unsigned int count)
{
socket_type client;
unsigned int i;
+ struct sockaddr *saddr;
+ socklen_t slen;
- client = network_accept_any(fds, count, NULL, NULL);
+ slen = sizeof(struct sockaddr_storage);
+ saddr = bmalloc(slen);
+ client = network_accept_any(fds, count, saddr, &slen);
listener_handler(client);
+ is_int(AF_INET, saddr->sa_family, "...address family is IPv4");
+ is_int(htonl(0x7f000001UL),
+ ((struct sockaddr_in *) saddr)->sin_addr.s_addr,
+ "...and client address is 127.0.0.1");
+ free(saddr);
for (i = 0; i < count; i++)
close(fds[i]);
}
@@ -105,17 +121,23 @@ listener_any(socket_type fds[], unsigned int count)
/*
* Connect to the given host on port 11119 and send a constant string to a
* socket, used to do the client side of the testing. Takes the source
- * address as well to pass into network_connect_host.
+ * address as well to pass into network_connect_host. If the flag is true,
+ * expects to succeed in connecting; otherwise, fail the test if the
+ * connection is successful.
*/
static void
-client(const char *host, const char *source)
+client(const char *host, const char *source, bool succeed)
{
socket_type fd;
FILE *out;
- fd = network_connect_host(host, 11119, source);
- if (fd == INVALID_SOCKET)
- sysdie("connect failed");
+ fd = network_connect_host(host, 11119, source, 0);
+ if (fd == INVALID_SOCKET) {
+ if (succeed)
+ _exit(1);
+ else
+ return;
+ }
out = fdopen(fd, "w");
if (out == NULL)
sysdie("fdopen failed");
@@ -149,7 +171,7 @@ test_ipv4(const char *source)
sysbail("cannot fork");
else if (child == 0) {
close(fd);
- client("127.0.0.1", source);
+ client("127.0.0.1", source, true);
} else {
listener(fd);
waitpid(child, NULL, 0);
@@ -169,20 +191,21 @@ test_ipv6(const char *source)
{
socket_type fd;
pid_t child;
+ int status;
fd = network_bind_ipv6("::1", 11119);
if (fd == INVALID_SOCKET) {
if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT
|| errno == EADDRNOTAVAIL) {
ipv6 = 0;
- skip_block(3, "IPv6 not supported");
+ skip_block(4, "IPv6 not supported");
return;
} else
sysbail("cannot create socket");
}
if (listen(fd, 1) < 0) {
sysdiag("cannot listen to socket");
- ok_block(3, 0, "IPv6 server test");
+ ok_block(4, 0, "IPv6 server test");
} else {
ok(1, "IPv6 server test");
child = fork();
@@ -190,10 +213,14 @@ test_ipv6(const char *source)
sysbail("cannot fork");
else if (child == 0) {
close(fd);
- client("::1", source);
+#ifdef IPV6_V6ONLY
+ client("127.0.0.1", NULL, false);
+#endif
+ client("::1", source, true);
} else {
listener(fd);
- waitpid(child, NULL, 0);
+ waitpid(child, &status, 0);
+ is_int(0, status, "client made correct connections");
}
}
}
@@ -201,7 +228,7 @@ test_ipv6(const char *source)
static void
test_ipv6(const char *source UNUSED)
{
- skip_block(3, "IPv6 not supported");
+ skip_block(4, "IPv6 not supported");
}
#endif /* !HAVE_INET6 */
@@ -218,7 +245,8 @@ test_all(const char *source_ipv4, const char *source_ipv6 UNUSED)
unsigned int count, i;
pid_t child;
struct sockaddr_storage saddr;
- socklen_t size = sizeof(saddr);
+ socklen_t size;
+ int status;
network_bind_all(11119, &fds, &count);
if (count == 0)
@@ -234,29 +262,35 @@ test_all(const char *source_ipv4, const char *source_ipv6 UNUSED)
ok_block(3, 0, "all address server test");
} else {
ok(1, "all address server test (part %d)", i);
+ size = sizeof(saddr);
+ if (getsockname(fd, (struct sockaddr *) &saddr, &size) < 0)
+ sysbail("cannot getsockname");
child = fork();
if (child < 0)
sysbail("cannot fork");
else if (child == 0) {
- if (getsockname(fd, (struct sockaddr *) &saddr, &size) < 0)
- sysbail("cannot getsockname");
- if (saddr.ss_family == AF_INET)
- client("127.0.0.1", source_ipv4);
+ if (saddr.ss_family == AF_INET) {
+ client("::1", source_ipv6, false);
+ client("127.0.0.1", source_ipv4, true);
#ifdef HAVE_INET6
- else if (saddr.ss_family == AF_INET6)
- client("::1", source_ipv6);
+ } else if (saddr.ss_family == AF_INET6) {
+# ifdef IPV6_V6ONLY
+ client("127.0.0.1", source_ipv4, false);
+# endif
+ client("::1", source_ipv6, true);
#endif
- else
- skip_block(2, "unknown socket family %d", saddr.ss_family);
- size = sizeof(saddr);
+ }
+ _exit(1);
} else {
listener(fd);
- waitpid(child, NULL, 0);
+ waitpid(child, &status, 0);
+ is_int(0, status, "client made correct connections");
}
}
}
if (count == 1)
skip_block(3, "only one listening socket");
+ network_bind_all_free(fds);
}
@@ -283,11 +317,12 @@ test_any(void)
if (child < 0)
sysbail("cannot fork");
else if (child == 0)
- client("127.0.0.1", NULL);
+ client("127.0.0.1", NULL, true);
else {
listener_any(fds, count);
waitpid(child, NULL, 0);
}
+ network_bind_all_free(fds);
}
@@ -323,7 +358,7 @@ test_create_ipv4(const char *source)
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(11119);
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ sin.sin_addr.s_addr = htonl(0x7f000001UL);
if (connect(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
_exit(1);
out = fdopen(fd, "w");
@@ -341,6 +376,73 @@ test_create_ipv4(const char *source)
/*
+ * Test connect timeouts using IPv4. Bring up a server on port 11119 on the
+ * loopback address and test connections to it. The server only accepts one
+ * connection at a time, so the second connection will time out.
+ */
+static void
+test_timeout_ipv4(void)
+{
+ socket_type fd, c;
+ pid_t child;
+
+ fd = network_bind_ipv4("127.0.0.1", 11119);
+ if (fd == INVALID_SOCKET)
+ sysbail("cannot create or bind socket");
+ if (listen(fd, 1) < 0) {
+ sysdiag("cannot listen to socket");
+ ok_block(3, 0, "IPv4 network client with timeout");
+ close(fd);
+ return;
+ }
+ child = fork();
+ if (child < 0)
+ sysbail("cannot fork");
+ else if (child == 0) {
+ struct sockaddr_in sin;
+ socklen_t slen;
+
+ alarm(10);
+ c = accept(fd, &sin, &slen);
+ if (c == INVALID_SOCKET)
+ _exit(1);
+ sleep(9);
+ _exit(0);
+ } else {
+ socket_type block[20];
+ int i;
+
+ close(fd);
+ c = network_connect_host("127.0.0.1", 11119, NULL, 1);
+ ok(c != INVALID_SOCKET, "Timeout: first connection worked");
+
+ /*
+ * For some reason, despite a listening queue of only 1, it can take
+ * up to seven connections on Linux before connections start actually
+ * timing out.
+ */
+ alarm(10);
+ for (i = 0; i < (int) ARRAY_SIZE(block); i++) {
+ block[i] = network_connect_host("127.0.0.1", 11119, NULL, 1);
+ if (block[i] == INVALID_SOCKET)
+ break;
+ }
+ diag("Finally timed out on socket %d", i);
+ ok(block[i] == INVALID_SOCKET, "Timeout: later connection timed out");
+ is_int(ETIMEDOUT, socket_errno, "...with correct error");
+ alarm(0);
+ kill(child, SIGTERM);
+ waitpid(child, NULL, 0);
+ close(c);
+ for (; i >= 0; i--)
+ if (block[i] != INVALID_SOCKET)
+ close(block[i]);
+ }
+ close(fd);
+}
+
+
+/*
* Tests network_addr_compare. Takes the expected result, the two addresses,
* and the mask.
*/
@@ -369,7 +471,7 @@ main(void)
static const char *ipv6_addr = "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210";
#endif
- plan(89);
+ plan(100);
/*
* If IPv6 support appears to be available but doesn't work, we have to
@@ -397,6 +499,9 @@ main(void)
/* Test network_accept_any. */
test_any();
+ /* Test network_connect with a timeout. */
+ test_timeout_ipv4();
+
/*
* Now, test network_sockaddr_sprint, network_sockaddr_equal, and
* network_sockaddr_port.
@@ -439,6 +544,7 @@ main(void)
"...and not equal to IPv4");
ok(!network_sockaddr_equal(ai6->ai_addr, ai4->ai_addr),
"...other way around");
+ freeaddrinfo(ai6);
/* Test IPv4 mapped addresses. */
status = getaddrinfo("::ffff:7f00:1", NULL, &hints, &ai6);
@@ -459,6 +565,7 @@ main(void)
#else
skip_block(12, "IPv6 not supported");
#endif
+ freeaddrinfo(ai);
/* Check the domains of functions and their error handling. */
ai4->ai_addr->sa_family = AF_UNIX;
@@ -466,6 +573,7 @@ main(void)
"equal not equal with address mismatches");
is_int(0, network_sockaddr_port(ai4->ai_addr),
"port meaningless for AF_UNIX");
+ freeaddrinfo(ai4);
/* Tests for network_addr_compare. */
ok_addr(1, "127.0.0.1", "127.0.0.1", NULL);
diff --git a/tests/util/vector-t.c b/tests/util/vector-t.c
index 71c28c4..4848156 100644
--- a/tests/util/vector-t.c
+++ b/tests/util/vector-t.c
@@ -1,6 +1,9 @@
/*
* vector 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/tests/util/xmalloc-t b/tests/util/xmalloc-t
index 88145dd..4dadc65 100755
--- a/tests/util/xmalloc-t
+++ b/tests/util/xmalloc-t
@@ -2,6 +2,9 @@
#
# 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 2000, 2001, 2006 Russ Allbery <rra@stanford.edu>
# Copyright 2008, 2009, 2010
diff --git a/tests/util/xmalloc.c b/tests/util/xmalloc.c
index 2364d1f..14e5fed 100644
--- a/tests/util/xmalloc.c
+++ b/tests/util/xmalloc.c
@@ -1,6 +1,9 @@
/*
* Test suite for xmalloc and family.
*
+ * 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 2000, 2001, 2006 Russ Allbery <rra@stanford.edu>
* Copyright 2008
* The Board of Trustees of the Leland Stanford Junior University
@@ -76,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)
diff --git a/tests/util/xwrite-t.c b/tests/util/xwrite-t.c
index 399a5da..f1cab22 100644
--- a/tests/util/xwrite-t.c
+++ b/tests/util/xwrite-t.c
@@ -1,6 +1,9 @@
/*
* Test suite for xwrite, xwritev, and xpwrite.
*
+ * 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 2000, 2001, 2002, 2004 Russ Allbery <rra@stanford.edu>
* Copyright 2009
* The Board of Trustees of the Leland Stanford Junior University
diff --git a/util/concat.c b/util/concat.c
index 0525ddb..fb4afa8 100644
--- a/util/concat.c
+++ b/util/concat.c
@@ -18,6 +18,9 @@
* together and returned. This is useful for building file names where names
* that aren't fully qualified are qualified with some particular directory.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/util/concat.h b/util/concat.h
index 9712d70..960f242 100644
--- a/util/concat.h
+++ b/util/concat.h
@@ -1,6 +1,9 @@
/*
* Prototypes for string concatenation with dynamic memory allocation.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
diff --git a/util/fdflag.c b/util/fdflag.c
index bf3125e..1be200c 100644
--- a/util/fdflag.c
+++ b/util/fdflag.c
@@ -4,7 +4,10 @@
* Simple functions (wrappers around fcntl) to set or clear file descriptor
* flags like close-on-exec or nonblocking I/O.
*
- * Copyright 2008
+ * 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, 2011
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
@@ -30,16 +33,21 @@
#include <config.h>
#include <portable/system.h>
-#include <errno.h>
-#include <fcntl.h>
-#ifndef O_NONBLOCK
-# include <sys/ioctl.h>
-# if HAVE_SYS_FILIO_H
-# include <sys/filio.h>
+#ifdef _WIN32
+# include <winsock2.h>
+#else
+# include <errno.h>
+# include <fcntl.h>
+# ifndef O_NONBLOCK
+# include <sys/ioctl.h>
+# if HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+# endif
# endif
#endif
#include <util/fdflag.h>
+#include <util/macros.h>
/*
@@ -49,7 +57,17 @@
* One is supposed to retrieve the flags, add FD_CLOEXEC, and then set them,
* although I've never seen a system with any flags other than close-on-exec.
* Do it right anyway; it's not that expensive.
-*/
+ *
+ * Stub this out on Windows, where it's not supported (at least currently by
+ * this utility library).
+ */
+#ifdef _WIN32
+bool
+fdflag_close_exec(int fd UNUSED, bool flag UNUSED)
+{
+ return false;
+}
+#else
bool
fdflag_close_exec(int fd, bool flag)
{
@@ -61,17 +79,23 @@ fdflag_close_exec(int fd, bool flag)
mode = flag ? (oflag | FD_CLOEXEC) : (oflag & ~FD_CLOEXEC);
return (fcntl(fd, F_SETFD, mode) == 0);
}
+#endif
/*
* Set a file descriptor to nonblocking (or clear the nonblocking flag if flag
* is false), returning true on success and false on failure.
*
- * Always use O_NONBLOCK; O_NDELAY is not the same thing historically. The
- * semantics of O_NDELAY are that if the read would block, it returns 0
- * instead. This is indistinguishable from an end of file condition. POSIX
- * added O_NONBLOCK, which requires read to return -1 and set errno to EAGAIN,
- * which is what we want.
+ * For Windows, be aware that this will only work for sockets. For UNIX, you
+ * can pass a non-socket in and it will do the right thing, since UNIX doesn't
+ * distinguish, but Windows will not allow that. Thankfully, there's rarely
+ * any need to set non-sockets non-blocking.
+ *
+ * For UNIX, always use O_NONBLOCK; O_NDELAY is not the same thing
+ * historically. The semantics of O_NDELAY are that if the read would block,
+ * it returns 0 instead. This is indistinguishable from an end of file
+ * condition. POSIX added O_NONBLOCK, which requires read to return -1 and
+ * set errno to EAGAIN, which is what we want.
*
* FNDELAY (4.3BSD) originally did the correct thing, although it has a
* different incompatibility (affecting all users of a socket rather than just
@@ -93,9 +117,18 @@ fdflag_close_exec(int fd, bool flag)
* O_NONBLOCK). Accordingly, we currently unconditionally use O_NONBLOCK. If
* this causes too many problems, an autoconf test may be required.
*/
-#ifdef O_NONBLOCK
+#if defined(_WIN32)
+bool
+fdflag_nonblocking(socket_type fd, bool flag)
+{
+ u_long mode;
+
+ mode = flag ? 1 : 0;
+ return (ioctlsocket(fd, FIONBIO, &mode) == 0);
+}
+#elif defined(O_NONBLOCK)
bool
-fdflag_nonblocking(int fd, bool flag)
+fdflag_nonblocking(socket_type fd, bool flag)
{
int mode;
@@ -106,8 +139,8 @@ fdflag_nonblocking(int fd, bool flag)
return (fcntl(fd, F_SETFL, mode) == 0);
}
#else /* !O_NONBLOCK */
-int
-nonblocking(int fd, bool flag)
+bool
+fdflag_nonblocking(socket_type fd, bool flag)
{
int state;
diff --git a/util/fdflag.h b/util/fdflag.h
index 6b8af60..bed45da 100644
--- a/util/fdflag.h
+++ b/util/fdflag.h
@@ -1,7 +1,10 @@
/*
* Prototypes for setting or clearing file descriptor flags.
*
- * Copyright 2008, 2010
+ * 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, 2011
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
@@ -30,15 +33,22 @@
#include <config.h>
#include <portable/macros.h>
#include <portable/stdbool.h>
+#include <portable/socket.h>
BEGIN_DECLS
/* Default to a hidden visibility for all util functions. */
#pragma GCC visibility push(hidden)
-/* Set a file descriptor close-on-exec or nonblocking. */
+/*
+ * Set a file descriptor close-on-exec or nonblocking. fdflag_close_exec is
+ * not supported on Windows and will always return false. fdflag_nonblocking
+ * is defined to take a socket_type so that it can be supported on Windows.
+ * On UNIX systems, you can safely pass in a non-socket file descriptor, but
+ * be aware that this will fail to compile on Windows.
+ */
bool fdflag_close_exec(int fd, bool flag);
-bool fdflag_nonblocking(int fd, bool flag);
+bool fdflag_nonblocking(socket_type fd, bool flag);
/* Undo default visibility change. */
#pragma GCC visibility pop
diff --git a/util/macros.h b/util/macros.h
index 084a5a2..54faee5 100644
--- a/util/macros.h
+++ b/util/macros.h
@@ -1,6 +1,9 @@
/*
* 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -17,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.c b/util/messages.c
index 01038d6..52fcfb7 100644
--- a/util/messages.c
+++ b/util/messages.c
@@ -50,6 +50,9 @@
* generates given the format and arguments), a format, an argument list as a
* va_list, and the applicable errno value (if any).
*
+ * 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
@@ -204,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 05dacac..0f8b5b6 100644
--- a/util/messages.h
+++ b/util/messages.h
@@ -1,6 +1,9 @@
/*
* Prototypes for message and error reporting (possibly fatal).
*
+ * 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
@@ -91,7 +94,7 @@ void message_log_syslog_crit(size_t, const char *, va_list, int)
__attribute__((__nonnull__));
/* The type of a message handler. */
-typedef void (*message_handler_func)(size_t, const char *, va_list, int);
+typedef void (*message_handler_func)(unsigned int, const char *, va_list, int);
/* If non-NULL, called before exit and its return value passed to exit. */
extern int (*message_fatal_cleanup)(void);
diff --git a/util/network.c b/util/network.c
index 50d7f8d..b88f83b 100644
--- a/util/network.c
+++ b/util/network.c
@@ -10,6 +10,15 @@
* implementations for functions that aren't found on some pre-IPv6 systems.
* No other part of the source tree should have to care about IPv4 vs. IPv6.
*
+ * In this file, casts through void * or const void * of struct sockaddr *
+ * parameters are to silence gcc warnings with -Wcast-align. The specific
+ * address types often require stronger alignment than a struct sockaddr, and
+ * were originally allocated with that alignment. GCC doesn't have a good way
+ * of knowing that this code is correct.
+ *
+ * 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, 2011
* The Board of Trustees of the Leland Stanford Junior University
@@ -39,7 +48,14 @@
#include <portable/socket.h>
#include <errno.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <util/fdflag.h>
#include <util/messages.h>
#include <util/network.h>
#include <util/xmalloc.h>
@@ -218,7 +234,7 @@ network_bind_ipv6(const char *address, unsigned short port)
*/
#if HAVE_INET6
void
-network_bind_all(unsigned short port, int **fds, unsigned int *count)
+network_bind_all(unsigned short port, socket_type **fds, unsigned int *count)
{
struct addrinfo hints, *addrs, *addr;
unsigned int size;
@@ -245,7 +261,7 @@ network_bind_all(unsigned short port, int **fds, unsigned int *count)
* assuming an IPv6 and IPv4 socket, and grow it by two when necessary.
*/
size = 2;
- *fds = xmalloc(size * sizeof(int));
+ *fds = xmalloc(size * sizeof(socket_type));
for (addr = addrs; addr != NULL; addr = addr->ai_next) {
network_sockaddr_sprint(name, sizeof(name), addr->ai_addr);
if (addr->ai_family == AF_INET)
@@ -285,6 +301,18 @@ network_bind_all(unsigned short port, socket_type **fds, unsigned int *count)
/*
+ * Free the array of file descriptors allocated by network_bind_all. This is
+ * a simple wrapper around free, needed on platforms where libraries allocate
+ * memory from a different memory domain than programs (such as Windows).
+ */
+void
+network_bind_all_free(socket_type *fds)
+{
+ free(fds);
+}
+
+
+/*
* Given an array of file descriptors and the length of that array (the same
* data that's returned by network_bind_all), wait for an incoming connection
* on any of those sockets, accept the connection with accept(), and return
@@ -327,7 +355,10 @@ network_accept_any(socket_type fds[], unsigned int count,
fd = fds[i];
break;
}
- return accept(fd, addr, addrlen);
+ if (fd == INVALID_SOCKET)
+ return INVALID_SOCKET;
+ else
+ return accept(fd, addr, addrlen);
}
@@ -336,18 +367,18 @@ network_accept_any(socket_type fds[], unsigned int count,
* using the provided source address. Returns true on success and false on
* failure.
*/
-static int
+static bool
network_source(socket_type fd, int family, const char *source)
{
if (source == NULL || strcmp(source, "all") == 0)
- return 1;
+ return true;
if (family == AF_INET) {
struct sockaddr_in saddr;
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
if (!inet_aton(source, &saddr.sin_addr))
- return 0;
+ return false;
return bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) == 0;
}
#ifdef HAVE_INET6
@@ -357,7 +388,7 @@ network_source(socket_type fd, int family, const char *source)
memset(&saddr, 0, sizeof(saddr));
saddr.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, source, &saddr.sin6_addr) < 1)
- return 0;
+ return false;
return bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) == 0;
}
#endif
@@ -367,7 +398,7 @@ network_source(socket_type fd, int family, const char *source)
#else
socket_set_errno(EINVAL);
#endif
- return 0;
+ return false;
}
}
@@ -381,13 +412,15 @@ network_source(socket_type fd, int family, const char *source)
* errno.
*/
socket_type
-network_connect(struct addrinfo *ai, const char *source)
+network_connect(struct addrinfo *ai, const char *source, time_t timeout)
{
socket_type fd = INVALID_SOCKET;
- int oerrno;
- int success;
+ int oerrno, status, err;
+ socklen_t len;
+ struct timeval tv;
+ fd_set set;
- for (success = 0; ai != NULL; ai = ai->ai_next) {
+ for (status = -1; status != 0 && ai != NULL; ai = ai->ai_next) {
if (fd != INVALID_SOCKET)
socket_close(fd);
fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
@@ -395,15 +428,34 @@ network_connect(struct addrinfo *ai, const char *source)
continue;
if (!network_source(fd, ai->ai_family, source))
continue;
- if (connect(fd, ai->ai_addr, ai->ai_addrlen) == 0) {
- success = 1;
- break;
+ if (timeout == 0)
+ status = connect(fd, ai->ai_addr, ai->ai_addrlen);
+ else {
+ fdflag_nonblocking(fd, true);
+ status = connect(fd, ai->ai_addr, ai->ai_addrlen);
+ if (status < 0 && socket_errno == EINPROGRESS) {
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+ status = select(fd + 1, NULL, &set, NULL, &tv);
+ if (status == 0 && !FD_ISSET(fd, &set)) {
+ status = -1;
+ socket_set_errno(ETIMEDOUT);
+ } else if (status > 0 && FD_ISSET(fd, &set)) {
+ len = sizeof(err);
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
+ if (status == 0)
+ status = err;
+ }
+ }
+ fdflag_nonblocking(fd, false);
}
}
- if (success)
+ if (status == 0)
return fd;
else {
- if (fd >= 0) {
+ if (fd != INVALID_SOCKET) {
oerrno = socket_errno;
socket_close(fd);
socket_set_errno(oerrno);
@@ -421,7 +473,7 @@ network_connect(struct addrinfo *ai, const char *source)
*/
socket_type
network_connect_host(const char *host, unsigned short port,
- const char *source)
+ const char *source, time_t timeout)
{
struct addrinfo hints, *ai;
char portbuf[16];
@@ -434,7 +486,7 @@ network_connect_host(const char *host, unsigned short port,
snprintf(portbuf, sizeof(portbuf), "%d", port);
if (getaddrinfo(host, portbuf, &hints, &ai) != 0)
return INVALID_SOCKET;
- fd = network_connect(ai, source);
+ fd = network_connect(ai, source, timeout);
oerrno = socket_errno;
freeaddrinfo(ai);
socket_set_errno(oerrno);
@@ -483,7 +535,7 @@ network_sockaddr_sprint(char *dst, size_t size, const struct sockaddr *addr)
if (addr->sa_family == AF_INET6) {
const struct sockaddr_in6 *sin6;
- sin6 = (const struct sockaddr_in6 *) addr;
+ sin6 = (const struct sockaddr_in6 *) (const void *) addr;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
struct in_addr in;
@@ -497,7 +549,7 @@ network_sockaddr_sprint(char *dst, size_t size, const struct sockaddr *addr)
if (addr->sa_family == AF_INET) {
const struct sockaddr_in *sin;
- sin = (const struct sockaddr_in *) addr;
+ sin = (const struct sockaddr_in *) (const void *) addr;
result = inet_ntop(AF_INET, &sin->sin_addr, dst, size);
return (result != NULL);
} else {
@@ -515,20 +567,26 @@ network_sockaddr_sprint(char *dst, size_t size, const struct sockaddr *addr)
bool
network_sockaddr_equal(const struct sockaddr *a, const struct sockaddr *b)
{
- const struct sockaddr_in *a4 = (const struct sockaddr_in *) a;
- const struct sockaddr_in *b4 = (const struct sockaddr_in *) b;
-
+ const struct sockaddr_in *a4;
+ const struct sockaddr_in *b4;
#ifdef HAVE_INET6
- const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) a;
- const struct sockaddr_in6 *b6 = (const struct sockaddr_in6 *) b;
+ const struct sockaddr_in6 *a6;
+ const struct sockaddr_in6 *b6;
const struct sockaddr *tmp;
+#endif
+
+ a4 = (const struct sockaddr_in *) (const void *) a;
+ b4 = (const struct sockaddr_in *) (const void *) b;
+#ifdef HAVE_INET6
+ a6 = (const struct sockaddr_in6 *) (const void *) a;
+ b6 = (const struct sockaddr_in6 *) (const void *) b;
if (a->sa_family == AF_INET && b->sa_family == AF_INET6) {
tmp = a;
a = b;
b = tmp;
- a6 = (const struct sockaddr_in6 *) a;
- b4 = (const struct sockaddr_in *) b;
+ a6 = (const struct sockaddr_in6 *) (const void *) a;
+ b4 = (const struct sockaddr_in *) (const void *) b;
}
if (a->sa_family == AF_INET6) {
if (b->sa_family == AF_INET6)
@@ -564,14 +622,14 @@ network_sockaddr_port(const struct sockaddr *sa)
const struct sockaddr_in6 *sin6;
if (sa->sa_family == AF_INET6) {
- sin6 = (const struct sockaddr_in6 *) sa;
+ sin6 = (const struct sockaddr_in6 *) (const void *) sa;
return htons(sin6->sin6_port);
}
#endif
if (sa->sa_family != AF_INET)
return 0;
else {
- sin = (const struct sockaddr_in *) sa;
+ sin = (const struct sockaddr_in *) (const void *) sa;
return htons(sin->sin_port);
}
}
diff --git a/util/network.h b/util/network.h
index d528a1a..5c4d981 100644
--- a/util/network.h
+++ b/util/network.h
@@ -1,6 +1,9 @@
/*
* Prototypes for network connection utility 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/>.
+ *
* Written by Russ Allbery <rra@stanford.edu>
* Copyright 2009, 2010, 2011
* The Board of Trustees of the Leland Stanford Junior University
@@ -56,11 +59,13 @@ socket_type network_bind_ipv6(const char *address, unsigned short port)
* and one for IPv6, if IPv6 support is enabled). If IPv6 is not enabled,
* just one socket will be created and bound to the IPv4 wildcard address.
* fds will be set to an array containing the resulting file descriptors, with
- * count holding the count returned.
+ * count holding the count returned. Use network_bind_all_free to free the
+ * array of file descriptors when no longer needed.
*/
void network_bind_all(unsigned short port, socket_type **fds,
unsigned int *count)
__attribute__((__nonnull__));
+void network_bind_all_free(socket_type *fds);
/*
* Accept an incoming connection from any file descriptor in an array. This
@@ -78,9 +83,9 @@ socket_type network_accept_any(socket_type fds[], unsigned int count,
* Create a socket and connect it to the remote service given by the linked
* list of addrinfo structs. Returns the new file descriptor on success and
* -1 on failure, with the error left in errno. Takes an optional source
- * address.
+ * address and a timeout in seconds, which may be 0 for no timeout.
*/
-socket_type network_connect(struct addrinfo *, const char *source)
+socket_type network_connect(struct addrinfo *, const char *source, time_t)
__attribute__((__nonnull__(1)));
/*
@@ -88,7 +93,7 @@ socket_type network_connect(struct addrinfo *, const char *source)
* fails, errno may not be set to anything useful.
*/
socket_type network_connect_host(const char *host, unsigned short port,
- const char *source)
+ const char *source, time_t)
__attribute__((__nonnull__(1)));
/*
diff --git a/util/vector.c b/util/vector.c
index 5138438..285969c 100644
--- a/util/vector.c
+++ b/util/vector.c
@@ -20,6 +20,9 @@
* and perform the same operations, but I'm leery of doing that as I'm not
* sure if it's a violation of the C type aliasing rules.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -345,7 +348,7 @@ vector_split_multi(const char *string, const char *seps,
if (vector->allocated < count)
vector_resize(vector, count);
- for (start = string, p = string, i = 0; *p; p++)
+ for (start = string, p = string, i = 0; *p != '\0'; p++)
if (strchr(seps, *p) != NULL) {
if (start != p)
vector->strings[i++] = xstrndup(start, p - start);
@@ -378,7 +381,7 @@ cvector_split_multi(char *string, const char *seps, struct cvector *vector)
if (vector->allocated < count)
cvector_resize(vector, count);
- for (start = string, p = string, i = 0; *p; p++)
+ for (start = string, p = string, i = 0; *p != '\0'; p++)
if (strchr(seps, *p) != NULL) {
if (start != p) {
*p = '\0';
@@ -438,7 +441,7 @@ vector_split_space(const char *string, struct vector *vector)
if (vector->allocated < count)
vector_resize(vector, count);
- for (start = string, p = string, i = 0; *p; p++)
+ for (start = string, p = string, i = 0; *p != '\0'; p++)
if (*p == ' ' || *p == '\t') {
if (start != p)
vector->strings[i++] = xstrndup(start, p - start);
@@ -470,7 +473,7 @@ cvector_split_space(char *string, struct cvector *vector)
if (vector->allocated < count)
cvector_resize(vector, count);
- for (start = string, p = string, i = 0; *p; p++)
+ for (start = string, p = string, i = 0; *p != '\0'; p++)
if (*p == ' ' || *p == '\t') {
if (start != p) {
*p = '\0';
diff --git a/util/vector.h b/util/vector.h
index ac3bf18..6a872d3 100644
--- a/util/vector.h
+++ b/util/vector.h
@@ -8,6 +8,9 @@
* Vectors require list of strings, not arbitrary binary data, and cannot
* handle data elements containing nul characters.
*
+ * 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>
*
* The authors hereby relinquish any claim to any copyright that they may have
@@ -97,7 +100,9 @@ void cvector_free(struct cvector *)
* Empty strings will yield zero-length vectors. Adjacent delimiters are
* treated as a single delimiter by *_split_space and *_split_multi, but *not*
* by *_split, so callers of *_split should be prepared for zero-length
- * strings in the vector.
+ * strings in the vector. *_split_space and *_split_multi ignore any leading
+ * or trailing delimiters, so those functions will never create zero-length
+ * strings (similar to the behavior of strtok).
*/
struct vector *vector_split(const char *string, char sep, struct vector *)
__attribute__((__nonnull__(1)));
diff --git a/util/xmalloc.c b/util/xmalloc.c
index 0803999..839f5a0 100644
--- a/util/xmalloc.c
+++ b/util/xmalloc.c
@@ -55,6 +55,9 @@
* 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 (c) 2004, 2005, 2006
* by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
diff --git a/util/xmalloc.h b/util/xmalloc.h
index 5447335..14d8831 100644
--- a/util/xmalloc.h
+++ b/util/xmalloc.h
@@ -1,6 +1,9 @@
/*
* Prototypes for malloc routines with failure 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 2010
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
diff --git a/util/xwrite.c b/util/xwrite.c
index 7e27654..8d472a7 100644
--- a/util/xwrite.c
+++ b/util/xwrite.c
@@ -21,6 +21,9 @@
* written, on the subsequent additional write; in that case, these functions
* will return -1 and the number of bytes actually written will be lost.
*
+ * 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
* The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2004, 2005, 2006
diff --git a/util/xwrite.h b/util/xwrite.h
index d79e801..2822727 100644
--- a/util/xwrite.h
+++ b/util/xwrite.h
@@ -1,6 +1,9 @@
/*
* Prototypes for write and writev replacements to handle partial writes.
*
+ * 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