summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2010-04-02 14:28:42 -0700
committerRuss Allbery <rra@stanford.edu>2010-04-02 14:28:42 -0700
commit3a60bbc3e829fa8b52da1e2f975540e3ddf0b25b (patch)
tree6d2f4b656eaccc2aa35727d83433fb365046a88a /util
parent896ee60e721556d182d55b28335334140136da03 (diff)
Update to rra-c-util 2.4
* Improve network error handling with unknown address domains. * Disable xmalloc test except for maintainers. * Break util/util.h apart into separate header files. * Add additional GCC function attributes to utility libraries. * Use AC_TYPE_LONG_LONG_INT instead of AC_CHECK_TYPES([long long]). Separate the remctl-specific functions out of util/util.h instead into separate header files following the pattern of rra-c-util, and create a new util/protocol.h header for protocol constants.
Diffstat (limited to 'util')
-rw-r--r--util/concat.c3
-rw-r--r--util/concat.h36
-rw-r--r--util/fdflag.c2
-rw-r--r--util/fdflag.h34
-rw-r--r--util/gss-errors.c5
-rw-r--r--util/gss-errors.h34
-rw-r--r--util/gss-tokens.c9
-rw-r--r--util/gss-tokens.h44
-rw-r--r--util/macros.h17
-rw-r--r--util/messages.c4
-rw-r--r--util/messages.h96
-rw-r--r--util/network.c28
-rw-r--r--util/network.h108
-rw-r--r--util/protocol.h49
-rw-r--r--util/tokens.c7
-rw-r--r--util/tokens.h62
-rw-r--r--util/util.h412
-rw-r--r--util/vector.c3
-rw-r--r--util/vector.h122
-rw-r--r--util/xmalloc.c3
-rw-r--r--util/xmalloc.h100
-rw-r--r--util/xwrite.c2
-rw-r--r--util/xwrite.h46
23 files changed, 788 insertions, 438 deletions
diff --git a/util/concat.c b/util/concat.c
index bef67db..bdbd836 100644
--- a/util/concat.c
+++ b/util/concat.c
@@ -25,7 +25,8 @@
#include <config.h>
#include <portable/system.h>
-#include <util/util.h>
+#include <util/concat.h>
+#include <util/xmalloc.h>
/* Abbreviation for cleaner code. */
#define VA_NEXT(var, type) ((var) = (type) va_arg(args, type))
diff --git a/util/concat.h b/util/concat.h
new file mode 100644
index 0000000..ef8b38d
--- /dev/null
+++ b/util/concat.h
@@ -0,0 +1,36 @@
+/*
+ * Prototypes for string concatenation with dynamic memory allocation.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * This work is hereby placed in the public domain by its author.
+ */
+
+#ifndef UTIL_CONCAT_H
+#define UTIL_CONCAT_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/* Concatenate NULL-terminated strings into a newly allocated string. */
+char *concat(const char *first, ...)
+ __attribute__((__malloc__, __nonnull__(1)));
+
+/*
+ * Given a base path and a file name, create a newly allocated path string.
+ * The name will be appended to base with a / between them. Exceptionally, if
+ * name begins with a slash, it will be strdup'd and returned as-is.
+ */
+char *concatpath(const char *base, const char *name)
+ __attribute__((__malloc__, __nonnull__(2)));
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_CONCAT_H */
diff --git a/util/fdflag.c b/util/fdflag.c
index 6895730..989504a 100644
--- a/util/fdflag.c
+++ b/util/fdflag.c
@@ -25,7 +25,7 @@
# endif
#endif
-#include <util/util.h>
+#include <util/fdflag.h>
/*
diff --git a/util/fdflag.h b/util/fdflag.h
new file mode 100644
index 0000000..f7cf274
--- /dev/null
+++ b/util/fdflag.h
@@ -0,0 +1,34 @@
+/*
+ * Prototypes for setting or clearing file descriptor flags.
+ *
+ * Copyright 2008, 2010 Board of Trustees, Leland Stanford Jr. University
+ * Copyright (c) 2004, 2005, 2006
+ * by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_FDFLAG_H
+#define UTIL_FDFLAG_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+#include <portable/stdbool.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. */
+bool fdflag_close_exec(int fd, bool flag);
+bool fdflag_nonblocking(int fd, bool flag);
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_FDFLAG_H */
diff --git a/util/gss-errors.c b/util/gss-errors.c
index b6a4808..09d3a43 100644
--- a/util/gss-errors.c
+++ b/util/gss-errors.c
@@ -5,7 +5,7 @@
* client and the server.
*
* Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2007 Board of Trustees, Leland Stanford Jr. University
+ * Copyright 2007, 2010 Board of Trustees, Leland Stanford Jr. University
*
* See LICENSE for licensing terms.
*/
@@ -14,7 +14,8 @@
#include <portable/system.h>
#include <portable/gssapi.h>
-#include <util/util.h>
+#include <util/concat.h>
+#include <util/gss-errors.h>
/*
diff --git a/util/gss-errors.h b/util/gss-errors.h
new file mode 100644
index 0000000..1bc9e69
--- /dev/null
+++ b/util/gss-errors.h
@@ -0,0 +1,34 @@
+/*
+ * Prototypes for shared GSS-API error handling code.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Copyright 2007, 2010 Board of Trustees, Leland Stanford Jr. University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_GSS_ERRORS_H
+#define UTIL_GSS_ERRORS_H 1
+
+#include <config.h>
+#include <portable/gssapi.h>
+#include <portable/macros.h>
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Convert a GSS-API error code pair into a human-readable string. Returns a
+ * newly allocated string that the caller must free.
+ */
+char *gssapi_error_string(const char *prefix, OM_uint32, OM_uint32)
+ __attribute__((__malloc__, __nonnull__));
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_GSS_ERRORS_H */
diff --git a/util/gss-tokens.c b/util/gss-tokens.c
index 525314e..670fc50 100644
--- a/util/gss-tokens.c
+++ b/util/gss-tokens.c
@@ -9,17 +9,20 @@
*
* Originally written by Anton Ushakov
* Extensive modifications by Russ Allbery <rra@stanford.edu>
- * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
* Board of Trustees, Leland Stanford Jr. University
*
* See README for licensing terms.
*/
#include <config.h>
-#include <portable/system.h>
#include <portable/gssapi.h>
+#include <portable/socket.h>
+#include <portable/system.h>
-#include <util/util.h>
+#include <util/gss-tokens.h>
+#include <util/protocol.h>
+#include <util/tokens.h>
/*
* If we're running the test suite, call testing versions of the token
diff --git a/util/gss-tokens.h b/util/gss-tokens.h
new file mode 100644
index 0000000..bb0e6b2
--- /dev/null
+++ b/util/gss-tokens.h
@@ -0,0 +1,44 @@
+/*
+ * Prototypes for GSS token handling routines.
+ *
+ * Originally written by Anton Ushakov
+ * Extensive modifications by Russ Allbery <rra@stanford.edu>
+ * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ * Board of Trustees, Leland Stanford Jr. University
+ *
+ * See README for licensing terms.
+ */
+
+#ifndef UTIL_GSS_TOKENS_H
+#define UTIL_GSS_TOKENS_H 1
+
+#include <config.h>
+#include <portable/gssapi.h>
+#include <portable/macros.h>
+#include <portable/socket.h>
+#include <util/tokens.h>
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Sending and receiving tokens with a GSS-API protection layer applied. Do
+ * not use gss_release_buffer to free the token returned by token_recv; this
+ * will cause crashes on Windows. Call free on the value member instead. On
+ * a GSS-API failure, the major and minor status are returned in the final two
+ * arguments.
+ */
+enum token_status token_send_priv(socket_type, gss_ctx_id_t, int flags,
+ gss_buffer_t, OM_uint32 *, OM_uint32 *);
+enum token_status token_recv_priv(socket_type, gss_ctx_id_t, int *flags,
+ gss_buffer_t, size_t max, OM_uint32 *,
+ OM_uint32 *);
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_GSS_TOKENS_H */
diff --git a/util/macros.h b/util/macros.h
new file mode 100644
index 0000000..97b2c2b
--- /dev/null
+++ b/util/macros.h
@@ -0,0 +1,17 @@
+/*
+ * Some standard helpful macros.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * This work is hereby placed in the public domain by its author.
+ */
+
+#ifndef UTIL_MACROS_H
+#define UTIL_MACROS_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+/* Used for unused parameters to silence gcc warnings. */
+#define UNUSED __attribute__((__unused__))
+
+#endif /* UTIL_MACROS_H */
diff --git a/util/messages.c b/util/messages.c
index b46415f..ef920b2 100644
--- a/util/messages.c
+++ b/util/messages.c
@@ -77,7 +77,9 @@
# define LOG_CRIT EVENTLOG_ERROR_TYPE
#endif
-#include <util/util.h>
+#include <util/macros.h>
+#include <util/messages.h>
+#include <util/xmalloc.h>
/* The default handler lists. */
static message_handler_func stdout_handlers[2] = {
diff --git a/util/messages.h b/util/messages.h
new file mode 100644
index 0000000..ff86f39
--- /dev/null
+++ b/util/messages.h
@@ -0,0 +1,96 @@
+/*
+ * Prototypes for message and error reporting (possibly fatal).
+ *
+ * Copyright 2008, 2010 Board of Trustees, Leland Stanford Jr. University
+ * Copyright (c) 2004, 2005, 2006
+ * by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_MESSAGES_H
+#define UTIL_MESSAGES_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+#include <stdarg.h>
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * The reporting functions. The ones prefaced by "sys" add a colon, a space,
+ * and the results of strerror(errno) to the output and are intended for
+ * reporting failures of system calls.
+ */
+void debug(const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 1, 2)));
+void notice(const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 1, 2)));
+void sysnotice(const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 1, 2)));
+void warn(const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 1, 2)));
+void syswarn(const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 1, 2)));
+void die(const char *, ...)
+ __attribute__((__nonnull__, __noreturn__, __format__(printf, 1, 2)));
+void sysdie(const char *, ...)
+ __attribute__((__nonnull__, __noreturn__, __format__(printf, 1, 2)));
+
+/*
+ * Set the handlers for various message functions. All of these functions
+ * take a count of the number of handlers and then function pointers for each
+ * of those handlers. These functions are not thread-safe; they set global
+ * variables.
+ */
+void message_handlers_debug(int count, ...);
+void message_handlers_notice(int count, ...);
+void message_handlers_warn(int count, ...);
+void message_handlers_die(int count, ...);
+
+/*
+ * Some useful handlers, intended to be passed to message_handlers_*. All
+ * handlers take the length of the formatted message, the format, a variadic
+ * argument list, and the errno setting if any.
+ */
+void message_log_stdout(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_stderr(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_syslog_debug(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_syslog_info(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_syslog_notice(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_syslog_warning(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_syslog_err(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+void message_log_syslog_crit(int, const char *, va_list, int)
+ __attribute((__nonnull__));
+
+/* The type of a message handler. */
+typedef void (*message_handler_func)(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);
+
+/*
+ * If non-NULL, prepended (followed by ": ") to all messages printed by either
+ * message_log_stdout or message_log_stderr.
+ */
+extern const char *message_program_name;
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_MESSAGES_H */
diff --git a/util/network.c b/util/network.c
index fd49b3a..2934635 100644
--- a/util/network.c
+++ b/util/network.c
@@ -8,7 +8,7 @@
* All of the portability difficulties with supporting IPv4 and IPv6 should be
* encapsulated in the combination of this code and replacement
* implementations for functions that aren't found on some pre-IPv6 systems.
- * No other part of remctl should have to care about IPv4 vs. IPv6.
+ * No other part of the source tree should have to care about IPv4 vs. IPv6.
*
* Copyright 2009 Board of Trustees, Leland Stanford Jr. University
* Copyright (c) 2004, 2005, 2006, 2007, 2008
@@ -25,7 +25,9 @@
#include <errno.h>
-#include <util/util.h>
+#include <util/messages.h>
+#include <util/network.h>
+#include <util/xmalloc.h>
/* Macros to set the len attribute of sockaddrs. */
#if HAVE_STRUCT_SOCKADDR_SA_LEN
@@ -229,20 +231,18 @@ network_bind_all(unsigned short port, socket_type **fds, int *count)
/*
- * Binds the given socket to an appropriate source address for its family,
- * using innconf information or the provided source address. Returns true on
- * success and false on failure.
+ * Binds the given socket to an appropriate source address for its family
+ * using the provided source address. Returns true on success and false on
+ * failure.
*/
static int
network_source(socket_type fd, int family, const char *source)
{
- if (source == NULL)
+ if (source == NULL || strcmp(source, "all") == 0)
return 1;
if (family == AF_INET) {
struct sockaddr_in saddr;
- if (source == NULL || strcmp(source, "all") == 0)
- return 1;
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
if (!inet_aton(source, &saddr.sin_addr))
@@ -253,8 +253,6 @@ network_source(socket_type fd, int family, const char *source)
else if (family == AF_INET6) {
struct sockaddr_in6 saddr;
- if (source == NULL || strcmp(source, "all") == 0)
- return 1;
memset(&saddr, 0, sizeof(saddr));
saddr.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, source, &saddr.sin6_addr) < 1)
@@ -262,8 +260,14 @@ network_source(socket_type fd, int family, const char *source)
return bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) == 0;
}
#endif
- else
- return 1;
+ else {
+#ifdef _WIN32
+ socket_set_errno(WSAEINVAL);
+#else
+ socket_set_errno(EINVAL);
+#endif
+ return 0;
+ }
}
diff --git a/util/network.h b/util/network.h
new file mode 100644
index 0000000..48afc8e
--- /dev/null
+++ b/util/network.h
@@ -0,0 +1,108 @@
+/*
+ * Prototypes for network connection utility functions.
+ *
+ * Copyright 2009, 2010 Board of Trustees, Leland Stanford Jr. University
+ * Copyright (c) 2004, 2005, 2006, 2007, 2008, 2010
+ * by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_NETWORK_H
+#define UTIL_NETWORK_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+#include <portable/socket.h>
+#include <portable/stdbool.h>
+
+#include <sys/types.h>
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Create a socket and bind it to the specified address and port (either IPv4
+ * or IPv6), returning the resulting file descriptor or -1 on error. Errors
+ * are reported using warn/syswarn. To bind to all interfaces, use "any" or
+ * "all" for address.
+ */
+socket_type network_bind_ipv4(const char *address, unsigned short port)
+ __attribute__((__nonnull__));
+socket_type network_bind_ipv6(const char *address, unsigned short port)
+ __attribute__((__nonnull__));
+
+/*
+ * Create and bind sockets for every local address (normally two, one for IPv4
+ * 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.
+ */
+void network_bind_all(unsigned short port, socket_type **fds, int *count)
+ __attribute__((__nonnull__));
+
+/*
+ * 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.
+ */
+socket_type network_connect(struct addrinfo *, const char *source)
+ __attribute__((__nonnull__(1)));
+
+/*
+ * Like network_connect but takes a host and port instead. If host lookup
+ * fails, errno may not be set to anything useful.
+ */
+socket_type network_connect_host(const char *host, unsigned short port,
+ const char *source)
+ __attribute__((__nonnull__(1)));
+
+/*
+ * Creates a socket of the specified domain and type and binds it to the
+ * appropriate source address, either the one supplied or all addresses if the
+ * source address is NULL or "all". Returns the newly created file descriptor
+ * or -1 on error.
+ *
+ * This is a lower-level function intended primarily for the use of clients
+ * that will then go on to do a non-blocking connect.
+ */
+socket_type network_client_create(int domain, int type, const char *source);
+
+/*
+ * Put an ASCII representation of the address in a sockaddr into the provided
+ * buffer, which should hold at least INET6_ADDRSTRLEN characters.
+ */
+bool network_sockaddr_sprint(char *, size_t, const struct sockaddr *)
+ __attribute__((__nonnull__));
+
+/*
+ * Returns if the addresses from the two sockaddrs are equal. The ports are
+ * ignored, and only AF_INET or AF_INET6 sockaddrs are supported (all others
+ * will return false).
+ */
+bool network_sockaddr_equal(const struct sockaddr *, const struct sockaddr *)
+ __attribute__((__nonnull__));
+
+/* Returns the port number from a sockaddr. */
+unsigned short network_sockaddr_port(const struct sockaddr *)
+ __attribute__((__nonnull__));
+
+/*
+ * Compare two addresses relative to an optional mask. Returns true if
+ * they're equal, false otherwise or on a parse error.
+ */
+bool network_addr_match(const char *, const char *, const char *mask)
+ __attribute__((__nonnull__(1, 2)));
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_NETWORK_H */
diff --git a/util/protocol.h b/util/protocol.h
new file mode 100644
index 0000000..5e26d96
--- /dev/null
+++ b/util/protocol.h
@@ -0,0 +1,49 @@
+/*
+ * Internal remctl protocol constants.
+ *
+ * Various constants and values used throughout the remctl source. This
+ * should eventually move into a public header file.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * Based on prior work by Anton Ushakov
+ * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ * Board of Trustees, Leland Stanford Jr. University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_PROTOCOL_H
+#define UTIL_PROTOCOL_H 1
+
+/* Maximum lengths from the protocol specification of tokens and data. */
+#define TOKEN_MAX_LENGTH (1024 * 1024)
+#define TOKEN_MAX_DATA (64 * 1024)
+
+/* Message types. */
+enum message_types {
+ MESSAGE_COMMAND = 1,
+ MESSAGE_QUIT = 2,
+ MESSAGE_OUTPUT = 3,
+ MESSAGE_STATUS = 4,
+ MESSAGE_ERROR = 5,
+ MESSAGE_VERSION = 6
+};
+
+/* Windows uses this for something else. */
+#ifdef _WIN32
+# undef ERROR_BAD_COMMAND
+#endif
+
+/* Error codes. */
+enum error_codes {
+ ERROR_INTERNAL = 1, /* Internal server failure. */
+ ERROR_BAD_TOKEN = 2, /* Invalid format in token. */
+ ERROR_UNKNOWN_MESSAGE = 3, /* Unknown message type. */
+ ERROR_BAD_COMMAND = 4, /* Invalid command format in token. */
+ ERROR_UNKNOWN_COMMAND = 5, /* Unknown command. */
+ ERROR_ACCESS = 6, /* Access denied. */
+ ERROR_TOOMANY_ARGS = 7, /* Argument count exceeds server limit. */
+ ERROR_TOOMUCH_DATA = 8 /* Argument size exceeds server limit. */
+};
+
+#endif /* UTIL_PROTOCOL_H */
diff --git a/util/tokens.c b/util/tokens.c
index f7e2f35..0183817 100644
--- a/util/tokens.c
+++ b/util/tokens.c
@@ -7,20 +7,21 @@
*
* Originally written by Anton Ushakov
* Extensive modifications by Russ Allbery <rra@stanford.edu>
- * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
* Board of Trustees, Leland Stanford Jr. University
*
* See LICENSE for licensing terms.
*/
#include <config.h>
-#include <portable/system.h>
#include <portable/gssapi.h>
#include <portable/socket.h>
+#include <portable/system.h>
#include <errno.h>
-#include <util/util.h>
+#include <util/tokens.h>
+#include <util/xwrite.h>
/*
* Windows requires a different function when sending to sockets, but can't
diff --git a/util/tokens.h b/util/tokens.h
new file mode 100644
index 0000000..a977350
--- /dev/null
+++ b/util/tokens.h
@@ -0,0 +1,62 @@
+/*
+ * Prototypes for token handling routines.
+ *
+ * Originally written by Anton Ushakov
+ * Extensive modifications by Russ Allbery <rra@stanford.edu>
+ * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ * Board of Trustees, Leland Stanford Jr. University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_TOKENS_H
+#define UTIL_TOKENS_H 1
+
+#include <config.h>
+#include <portable/gssapi.h>
+#include <portable/macros.h>
+#include <portable/socket.h>
+#include <sys/types.h>
+
+/* Token types and flags. */
+enum token_flags {
+ TOKEN_NOOP = (1 << 0),
+ TOKEN_CONTEXT = (1 << 1),
+ TOKEN_DATA = (1 << 2),
+ TOKEN_MIC = (1 << 3),
+ TOKEN_CONTEXT_NEXT = (1 << 4),
+ TOKEN_SEND_MIC = (1 << 5),
+ TOKEN_PROTOCOL = (1 << 6)
+};
+
+/* Failure return codes from token_send and token_recv. */
+enum token_status {
+ TOKEN_OK = 0,
+ TOKEN_FAIL_SYSTEM = -1, /* System call failed, error in errno */
+ TOKEN_FAIL_SOCKET = -2, /* Socket call failed, error in socket_errno */
+ TOKEN_FAIL_INVALID = -3, /* Invalid token from remote site */
+ TOKEN_FAIL_LARGE = -4, /* Token data exceeds max length */
+ TOKEN_FAIL_EOF = -5, /* Unexpected end of file while reading */
+ TOKEN_FAIL_GSSAPI = -6 /* GSS-API failure {en,de}crypting token */
+};
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Sending and receiving tokens. Do not use gss_release_buffer to free the
+ * token returned by token_recv; this will cause crashes on Windows. Call
+ * free on the value member instead.
+ */
+enum token_status token_send(socket_type, int flags, gss_buffer_t);
+enum token_status token_recv(socket_type, int *flags, gss_buffer_t,
+ size_t max);
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_GSS_ERRORS_H */
diff --git a/util/util.h b/util/util.h
deleted file mode 100644
index 807b78c..0000000
--- a/util/util.h
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Utility functions.
- *
- * This is a variety of utility functions that are used internally by pieces
- * of remctl. Many of them came originally from INN.
- *
- * Written by Russ Allbery <rra@stanford.edu>
- * Based on prior work by Anton Ushakov
- * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- * Board of Trustees, Leland Stanford Jr. University
- * Copyright (c) 2004, 2005, 2006, 2007
- * by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- * 2002, 2003 by The Internet Software Consortium and Rich Salz
- *
- * See LICENSE for licensing terms.
- */
-
-#ifndef UTIL_UTIL_H
-#define UTIL_UTIL_H 1
-
-#include <config.h>
-#include <portable/gssapi.h>
-#include <portable/macros.h>
-#include <portable/socket.h>
-#include <portable/stdbool.h>
-
-#include <stdarg.h>
-#include <sys/types.h>
-
-/* Windows uses this for something else. */
-#ifdef _WIN32
-# undef ERROR_BAD_COMMAND
-#endif
-
-/* Used for unused parameters to silence gcc warnings. */
-#define UNUSED __attribute__((__unused__))
-
-BEGIN_DECLS
-
-/* Forward declarations to avoid includes. */
-struct addrinfo;
-struct iovec;
-struct sockaddr;
-
-/* Maximum lengths from the protocol specification of tokens and data. */
-#define TOKEN_MAX_LENGTH (1024 * 1024)
-#define TOKEN_MAX_DATA (64 * 1024)
-
-/* Failure return codes from token_send and token_recv. */
-enum token_status {
- TOKEN_OK = 0,
- TOKEN_FAIL_SYSTEM = -1, /* System call failed, error in errno */
- TOKEN_FAIL_SOCKET = -2, /* Socket call failed, error in socket_errno */
- TOKEN_FAIL_INVALID = -3, /* Invalid token from remote site */
- TOKEN_FAIL_LARGE = -4, /* Token data exceeds max length */
- TOKEN_FAIL_EOF = -5, /* Unexpected end of file while reading */
- TOKEN_FAIL_GSSAPI = -6 /* GSS-API failure {en,de}crypting token */
-};
-
-/* Token types and flags. */
-enum token_flags {
- TOKEN_NOOP = (1 << 0),
- TOKEN_CONTEXT = (1 << 1),
- TOKEN_DATA = (1 << 2),
- TOKEN_MIC = (1 << 3),
- TOKEN_CONTEXT_NEXT = (1 << 4),
- TOKEN_SEND_MIC = (1 << 5),
- TOKEN_PROTOCOL = (1 << 6)
-};
-
-/* Message types. */
-enum message_types {
- MESSAGE_COMMAND = 1,
- MESSAGE_QUIT = 2,
- MESSAGE_OUTPUT = 3,
- MESSAGE_STATUS = 4,
- MESSAGE_ERROR = 5,
- MESSAGE_VERSION = 6
-};
-
-/* Error codes. */
-enum error_codes {
- ERROR_INTERNAL = 1, /* Internal server failure. */
- ERROR_BAD_TOKEN = 2, /* Invalid format in token. */
- ERROR_UNKNOWN_MESSAGE = 3, /* Unknown message type. */
- ERROR_BAD_COMMAND = 4, /* Invalid command format in token. */
- ERROR_UNKNOWN_COMMAND = 5, /* Unknown command. */
- ERROR_ACCESS = 6, /* Access denied. */
- ERROR_TOOMANY_ARGS = 7, /* Argument count exceeds server limit. */
- ERROR_TOOMUCH_DATA = 8 /* Argument size exceeds server limit. */
-};
-
-/* Default to a hidden visibility for all util functions. */
-#pragma GCC visibility push(hidden)
-
-/*
- * Sending and receiving tokens. Do not use gss_release_buffer to free the
- * token returned by token_recv; this will cause crashes on Windows. Call
- * free on the value member instead.
- */
-enum token_status token_send(socket_type, int flags, gss_buffer_t);
-enum token_status token_recv(socket_type, int *flags, gss_buffer_t,
- size_t max);
-
-/*
- * The same, but with a GSS-API protection layer applied. On a GSS-API
- * failure, the major and minor status are returned in the final two
- * arguments.
- */
-enum token_status token_send_priv(socket_type, gss_ctx_id_t, int flags,
- gss_buffer_t, OM_uint32 *, OM_uint32 *);
-enum token_status token_recv_priv(socket_type, gss_ctx_id_t, int *flags,
- gss_buffer_t, size_t max, OM_uint32 *,
- OM_uint32 *);
-
-/*
- * Convert a GSS-API error code pair into a human-readable string. Returns a
- * newly allocated string that the caller must free.
- */
-char *gssapi_error_string(const char *prefix, OM_uint32, OM_uint32);
-
-/* Concatenate NULL-terminated strings into a newly allocated string. */
-char *concat(const char *first, ...);
-
-/*
- * Given a base path and a file name, create a newly allocated path string.
- * The name will be appended to base with a / between them. Exceptionally, if
- * name begins with a slash, it will be strdup'd and returned as-is.
- */
-char *concatpath(const char *base, const char *name);
-
-/*
- * Like the non-x versions of the same function, but keep writing until either
- * the write is not making progress or there's a real error. Handle partial
- * writes and EINTR/EAGAIN errors.
- */
-ssize_t xpwrite(int fd, const void *buffer, size_t size, off_t offset);
-ssize_t xwrite(int fd, const void *buffer, size_t size);
-ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt);
-
-/*
- * Create a socket and bind it to the specified address and port (either IPv4
- * or IPv6), returning the resulting file descriptor or -1 on error. Errors
- * are reported using warn/syswarn. To bind to all interfaces, use "any" or
- * "all" for address.
- */
-socket_type network_bind_ipv4(const char *address, unsigned short port);
-socket_type network_bind_ipv6(const char *address, unsigned short port);
-
-/*
- * Create and bind sockets for every local address (normally two, one for IPv4
- * 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.
- */
-void network_bind_all(unsigned short port, socket_type **fds, 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.
- */
-socket_type network_connect(struct addrinfo *, const char *source);
-
-/*
- * Like network_connect but takes a host and port instead. If host lookup
- * fails, errno may not be set to anything useful.
- */
-socket_type network_connect_host(const char *host, unsigned short port,
- const char *source);
-
-/*
- * Creates a socket of the specified domain and type and binds it to the
- * appropriate source address, either the one supplied or the appropriate
- * innconf setting if the provided source address is NULL. To bind to all
- * interfaces, use "all" for address. Returns the newly created file
- * descriptor or -1 on error.
- *
- * This is a lower-level function intended primarily for the use of clients
- * that will then go on to do a non-blocking connect.
- */
-socket_type network_client_create(int domain, int type, const char *source);
-
-/*
- * Put an ASCII representation of the address in a sockaddr into the provided
- * buffer, which should hold at least INET6_ADDRSTRLEN characters.
- */
-bool network_sockaddr_sprint(char *, size_t, const struct sockaddr *);
-
-/*
- * Returns if the addresses from the two sockaddrs are equal. The ports are
- * ignored, and only AF_INET or AF_INET6 sockaddrs are supported (all others
- * will return false).
- */
-bool network_sockaddr_equal(const struct sockaddr *, const struct sockaddr *);
-
-/* Returns the port number from a sockaddr. */
-unsigned short network_sockaddr_port(const struct sockaddr *);
-
-/*
- * Compare two addresses relative to an optional mask. Returns true if
- * they're equal, false otherwise or on a parse error.
- */
-bool network_addr_match(const char *, const char *, const char *mask);
-
-/* Set a file descriptor close-on-exec or nonblocking. */
-bool fdflag_close_exec(int fd, bool flag);
-bool fdflag_nonblocking(int fd, bool flag);
-
-/*
- * The reporting functions. The ones prefaced by "sys" add a colon, a space,
- * and the results of strerror(errno) to the output and are intended for
- * reporting failures of system calls.
- */
-void debug(const char *, ...)
- __attribute__((__format__(printf, 1, 2)));
-void notice(const char *, ...)
- __attribute__((__format__(printf, 1, 2)));
-void sysnotice(const char *, ...)
- __attribute__((__format__(printf, 1, 2)));
-void warn(const char *, ...)
- __attribute__((__format__(printf, 1, 2)));
-void syswarn(const char *, ...)
- __attribute__((__format__(printf, 1, 2)));
-void die(const char *, ...)
- __attribute__((__noreturn__, __format__(printf, 1, 2)));
-void sysdie(const char *, ...)
- __attribute__((__noreturn__, __format__(printf, 1, 2)));
-
-/*
- * Set the handlers for various message functions. All of these functions
- * take a count of the number of handlers and then function pointers for each
- * of those handlers. These functions are not thread-safe; they set global
- * variables.
- */
-void message_handlers_debug(int count, ...);
-void message_handlers_notice(int count, ...);
-void message_handlers_warn(int count, ...);
-void message_handlers_die(int count, ...);
-
-/*
- * Some useful handlers, intended to be passed to message_handlers_*. All
- * handlers take the length of the formatted message, the format, a variadic
- * argument list, and the errno setting if any.
- */
-void message_log_stdout(int, const char *, va_list, int);
-void message_log_stderr(int, const char *, va_list, int);
-void message_log_syslog_debug(int, const char *, va_list, int);
-void message_log_syslog_info(int, const char *, va_list, int);
-void message_log_syslog_notice(int, const char *, va_list, int);
-void message_log_syslog_warning(int, const char *, va_list, int);
-void message_log_syslog_err(int, const char *, va_list, int);
-void message_log_syslog_crit(int, const char *, va_list, int);
-
-/* The type of a message handler. */
-typedef void (*message_handler_func)(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);
-
-/*
- * If non-NULL, prepended (followed by ": ") to all messages printed by either
- * message_log_stdout or message_log_stderr.
- */
-extern const char *message_program_name;
-
-struct vector {
- size_t count;
- size_t allocated;
- char **strings;
-};
-
-struct cvector {
- size_t count;
- size_t allocated;
- const char **strings;
-};
-
-/* Create a new, empty vector. */
-struct vector *vector_new(void);
-struct cvector *cvector_new(void);
-
-/* Add a string to a vector. Resizes the vector if necessary. */
-void vector_add(struct vector *, const char *string);
-void cvector_add(struct cvector *, const char *string);
-
-/* Add a counted string to a vector. Only available for vectors. */
-void vector_addn(struct vector *, const char *string, size_t length);
-
-/*
- * Resize the array of strings to hold size entries. Saves reallocation work
- * in vector_add if it's known in advance how many entries there will be.
- */
-void vector_resize(struct vector *, size_t size);
-void cvector_resize(struct cvector *, size_t size);
-
-/*
- * Reset the number of elements to zero, freeing all of the strings for a
- * regular vector, but not freeing the strings array (to cut down on memory
- * allocations if the vector will be reused).
- */
-void vector_clear(struct vector *);
-void cvector_clear(struct cvector *);
-
-/* Free the vector and all resources allocated for it. */
-void vector_free(struct vector *);
-void cvector_free(struct cvector *);
-
-/*
- * Split functions build a vector from a string. vector_split splits on a
- * specified character, while vector_split_space splits on any sequence of
- * spaces or tabs (not any sequence of whitespace, as just spaces or tabs is
- * more useful). The cvector versions destructively modify the provided
- * string in-place to insert nul characters between the strings. If the
- * vector argument is NULL, a new vector is allocated; otherwise, the provided
- * one is reused.
- *
- * Empty strings will yield zero-length vectors. Adjacent delimiters are
- * treated as a single delimiter by *_split_space, but *not* by *_split, so
- * callers of *_split should be prepared for zero-length strings in the
- * vector.
- */
-struct vector *vector_split(const char *string, char sep, struct vector *);
-struct vector *vector_split_space(const char *string, struct vector *);
-struct cvector *cvector_split(char *string, char sep, struct cvector *);
-struct cvector *cvector_split_space(char *string, struct cvector *);
-
-/*
- * Build a string from a vector by joining its components together with the
- * specified string as separator. Returns a newly allocated string; caller is
- * responsible for freeing.
- */
-char *vector_join(const struct vector *, const char *seperator);
-char *cvector_join(const struct cvector *, const char *separator);
-
-/*
- * Exec the given program with the vector as its arguments. Return behavior
- * is the same as execv. Note the argument order is different than the other
- * vector functions (but the same as execv).
- */
-int vector_exec(const char *path, struct vector *);
-int cvector_exec(const char *path, struct cvector *);
-
-/*
- * The functions are actually macros so that we can pick up the file and line
- * number information for debugging error messages without the user having to
- * pass those in every time.
- */
-#define xcalloc(n, size) x_calloc((n), (size), __FILE__, __LINE__)
-#define xmalloc(size) x_malloc((size), __FILE__, __LINE__)
-#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__)
-#define xstrdup(p) x_strdup((p), __FILE__, __LINE__)
-#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__)
-#define xvasprintf(p, f, a) x_vasprintf((p), (f), (a), __FILE__, __LINE__)
-
-/*
- * asprintf is a special case since it takes variable arguments. If we have
- * support for variadic macros, we can still pass in the file and line and
- * just need to put them somewhere else in the argument list than last.
- * Otherwise, just call x_asprintf directly. This means that the number of
- * arguments x_asprintf takes must vary depending on whether variadic macros
- * are supported.
- */
-#ifdef HAVE_C99_VAMACROS
-# define xasprintf(p, f, ...) \
- x_asprintf((p), __FILE__, __LINE__, (f), __VA_ARGS__)
-#elif HAVE_GNU_VAMACROS
-# define xasprintf(p, f, args...) \
- x_asprintf((p), __FILE__, __LINE__, (f), args)
-#else
-# define xasprintf x_asprintf
-#endif
-
-/*
- * Last two arguments are always file and line number. These are internal
- * implementations that should not be called directly.
- */
-void *x_calloc(size_t, size_t, const char *, int);
-void *x_malloc(size_t, const char *, int);
-void *x_realloc(void *, size_t, const char *, int);
-char *x_strdup(const char *, const char *, int);
-char *x_strndup(const char *, size_t, const char *, int);
-int x_vasprintf(char **, const char *, va_list, const char *, int);
-
-/* asprintf special case. */
-#if HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS
-int x_asprintf(char **, const char *, int, const char *, ...);
-#else
-int x_asprintf(char **, const char *, ...);
-#endif
-
-/* Failure handler takes the function, the size, the file, and the line. */
-typedef void (*xmalloc_handler_type)(const char *, size_t, const char *, int);
-
-/* The default error handler. */
-void xmalloc_fail(const char *, size_t, const char *, int);
-
-/*
- * Assign to this variable to choose a handler other than the default, which
- * just calls sysdie.
- */
-extern xmalloc_handler_type xmalloc_error_handler;
-
-/* Undo default visibility change. */
-#pragma GCC visibility pop
-
-END_DECLS
-
-#endif /* UTIL_UTIL_H */
diff --git a/util/vector.c b/util/vector.c
index 1c49986..2ed43e6 100644
--- a/util/vector.c
+++ b/util/vector.c
@@ -26,7 +26,8 @@
#include <ctype.h>
-#include <util/util.h>
+#include <util/vector.h>
+#include <util/xmalloc.h>
/*
diff --git a/util/vector.h b/util/vector.h
new file mode 100644
index 0000000..766bc2c
--- /dev/null
+++ b/util/vector.h
@@ -0,0 +1,122 @@
+/*
+ * Prototypes for vector handling.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * This work is hereby placed in the public domain by its author.
+ */
+
+#ifndef UTIL_VECTOR_H
+#define UTIL_VECTOR_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+#include <sys/types.h>
+
+struct vector {
+ size_t count;
+ size_t allocated;
+ char **strings;
+};
+
+struct cvector {
+ size_t count;
+ size_t allocated;
+ const char **strings;
+};
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/* Create a new, empty vector. */
+struct vector *vector_new(void)
+ __attribute__((__malloc__));
+struct cvector *cvector_new(void)
+ __attribute__((__malloc__));
+
+/* Add a string to a vector. Resizes the vector if necessary. */
+void vector_add(struct vector *, const char *string)
+ __attribute((__nonnull__));
+void cvector_add(struct cvector *, const char *string)
+ __attribute((__nonnull__));
+
+/* Add a counted string to a vector. Only available for vectors. */
+void vector_addn(struct vector *, const char *string, size_t length)
+ __attribute((__nonnull__));
+
+/*
+ * Resize the array of strings to hold size entries. Saves reallocation work
+ * in vector_add if it's known in advance how many entries there will be.
+ */
+void vector_resize(struct vector *, size_t size)
+ __attribute((__nonnull__));
+void cvector_resize(struct cvector *, size_t size)
+ __attribute((__nonnull__));
+
+/*
+ * Reset the number of elements to zero, freeing all of the strings for a
+ * regular vector, but not freeing the strings array (to cut down on memory
+ * allocations if the vector will be reused).
+ */
+void vector_clear(struct vector *)
+ __attribute((__nonnull__));
+void cvector_clear(struct cvector *)
+ __attribute((__nonnull__));
+
+/* Free the vector and all resources allocated for it. */
+void vector_free(struct vector *)
+ __attribute((__nonnull__));
+void cvector_free(struct cvector *)
+ __attribute((__nonnull__));
+
+/*
+ * Split functions build a vector from a string. vector_split splits on a
+ * specified character, while vector_split_space splits on any sequence of
+ * spaces or tabs (not any sequence of whitespace, as just spaces or tabs is
+ * more useful). The cvector versions destructively modify the provided
+ * string in-place to insert nul characters between the strings. If the
+ * vector argument is NULL, a new vector is allocated; otherwise, the provided
+ * one is reused.
+ *
+ * Empty strings will yield zero-length vectors. Adjacent delimiters are
+ * treated as a single delimiter by *_split_space, but *not* by *_split, so
+ * callers of *_split should be prepared for zero-length strings in the
+ * vector.
+ */
+struct vector *vector_split(const char *string, char sep, struct vector *)
+ __attribute((__nonnull__(1)));
+struct vector *vector_split_space(const char *string, struct vector *)
+ __attribute((__nonnull__(1)));
+struct cvector *cvector_split(char *string, char sep, struct cvector *)
+ __attribute((__nonnull__(1)));
+struct cvector *cvector_split_space(char *string, struct cvector *)
+ __attribute((__nonnull__(1)));
+
+/*
+ * Build a string from a vector by joining its components together with the
+ * specified string as separator. Returns a newly allocated string; caller is
+ * responsible for freeing.
+ */
+char *vector_join(const struct vector *, const char *seperator)
+ __attribute__((__malloc__, __nonnull__));
+char *cvector_join(const struct cvector *, const char *separator)
+ __attribute__((__malloc__, __nonnull__));
+
+/*
+ * Exec the given program with the vector as its arguments. Return behavior
+ * is the same as execv. Note the argument order is different than the other
+ * vector functions (but the same as execv).
+ */
+int vector_exec(const char *path, struct vector *)
+ __attribute((__nonnull__));
+int cvector_exec(const char *path, struct cvector *)
+ __attribute((__nonnull__));
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_VECTOR_H */
diff --git a/util/xmalloc.c b/util/xmalloc.c
index 5feb1ca..4e05f96 100644
--- a/util/xmalloc.c
+++ b/util/xmalloc.c
@@ -68,7 +68,8 @@
#include <errno.h>
-#include <util/util.h>
+#include <util/messages.h>
+#include <util/xmalloc.h>
/*
diff --git a/util/xmalloc.h b/util/xmalloc.h
new file mode 100644
index 0000000..657a6bb
--- /dev/null
+++ b/util/xmalloc.h
@@ -0,0 +1,100 @@
+/*
+ * Prototypes for malloc routines with failure handling.
+ *
+ * Copyright 2010 Board of Trustees, Leland Stanford Jr. University
+ * Copyright (c) 2004, 2005, 2006
+ * by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_XMALLOC_H
+#define UTIL_XMALLOC_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+#include <sys/types.h>
+
+/*
+ * The functions are actually macros so that we can pick up the file and line
+ * number information for debugging error messages without the user having to
+ * pass those in every time.
+ */
+#define xcalloc(n, size) x_calloc((n), (size), __FILE__, __LINE__)
+#define xmalloc(size) x_malloc((size), __FILE__, __LINE__)
+#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__)
+#define xstrdup(p) x_strdup((p), __FILE__, __LINE__)
+#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__)
+#define xvasprintf(p, f, a) x_vasprintf((p), (f), (a), __FILE__, __LINE__)
+
+/*
+ * asprintf is a special case since it takes variable arguments. If we have
+ * support for variadic macros, we can still pass in the file and line and
+ * just need to put them somewhere else in the argument list than last.
+ * Otherwise, just call x_asprintf directly. This means that the number of
+ * arguments x_asprintf takes must vary depending on whether variadic macros
+ * are supported.
+ */
+#ifdef HAVE_C99_VAMACROS
+# define xasprintf(p, f, ...) \
+ x_asprintf((p), __FILE__, __LINE__, (f), __VA_ARGS__)
+#elif HAVE_GNU_VAMACROS
+# define xasprintf(p, f, args...) \
+ x_asprintf((p), __FILE__, __LINE__, (f), args)
+#else
+# define xasprintf x_asprintf
+#endif
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Last two arguments are always file and line number. These are internal
+ * implementations that should not be called directly.
+ */
+void *x_calloc(size_t, size_t, const char *, int)
+ __attribute__((__alloc_size__(1, 2), __malloc__, __nonnull__));
+void *x_malloc(size_t, const char *, int)
+ __attribute__((__alloc_size__(1), __malloc__, __nonnull__));
+void *x_realloc(void *, size_t, const char *, int)
+ __attribute__((__alloc_size__(2), __malloc__, __nonnull__(3)));
+char *x_strdup(const char *, const char *, int)
+ __attribute__((__malloc__, __nonnull__));
+char *x_strndup(const char *, size_t, const char *, int)
+ __attribute__((__malloc__, __nonnull__));
+int x_vasprintf(char **, const char *, va_list, const char *, int)
+ __attribute__((__nonnull__));
+
+/* asprintf special case. */
+#if HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS
+int x_asprintf(char **, const char *, int, const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 4, 5)));
+#else
+int x_asprintf(char **, const char *, ...)
+ __attribute__((__nonnull__, __format__(printf, 2, 3)));
+#endif
+
+/* Failure handler takes the function, the size, the file, and the line. */
+typedef void (*xmalloc_handler_type)(const char *, size_t, const char *, int);
+
+/* The default error handler. */
+void xmalloc_fail(const char *, size_t, const char *, int)
+ __attribute__((__nonnull__));
+
+/*
+ * Assign to this variable to choose a handler other than the default, which
+ * just calls sysdie.
+ */
+extern xmalloc_handler_type xmalloc_error_handler;
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_XMALLOC_H */
diff --git a/util/xwrite.c b/util/xwrite.c
index 215f40e..a086a19 100644
--- a/util/xwrite.c
+++ b/util/xwrite.c
@@ -36,7 +36,7 @@
#include <errno.h>
-#include <util/util.h>
+#include <util/xwrite.h>
/*
* If we're running the test suite, call testing versions of the write
diff --git a/util/xwrite.h b/util/xwrite.h
new file mode 100644
index 0000000..72cf335
--- /dev/null
+++ b/util/xwrite.h
@@ -0,0 +1,46 @@
+/*
+ * Prototypes for write and writev replacements to handle partial writes.
+ *
+ * Copyright 2008, 2010 Board of Trustees, Leland Stanford Jr. University
+ * Copyright (c) 2004, 2005, 2006
+ * by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ * 2002, 2003 by The Internet Software Consortium and Rich Salz
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#ifndef UTIL_XWRITE_H
+#define UTIL_XWRITE_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+#include <sys/types.h>
+
+/* Forward declaration to avoid an include. */
+struct iovec;
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Like the non-x versions of the same function, but keep writing until either
+ * the write is not making progress or there's a real error. Handle partial
+ * writes and EINTR/EAGAIN errors.
+ */
+ssize_t xpwrite(int fd, const void *buffer, size_t size, off_t offset)
+ __attribute__((__nonnull__));
+ssize_t xwrite(int fd, const void *buffer, size_t size)
+ __attribute__((__nonnull__));
+ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt)
+ __attribute__((__nonnull__));
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_XWRITE_H */