diff options
author | Russ Allbery <rra@stanford.edu> | 2010-04-02 14:28:42 -0700 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2010-04-02 14:28:42 -0700 |
commit | 3a60bbc3e829fa8b52da1e2f975540e3ddf0b25b (patch) | |
tree | 6d2f4b656eaccc2aa35727d83433fb365046a88a /util | |
parent | 896ee60e721556d182d55b28335334140136da03 (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.c | 3 | ||||
-rw-r--r-- | util/concat.h | 36 | ||||
-rw-r--r-- | util/fdflag.c | 2 | ||||
-rw-r--r-- | util/fdflag.h | 34 | ||||
-rw-r--r-- | util/gss-errors.c | 5 | ||||
-rw-r--r-- | util/gss-errors.h | 34 | ||||
-rw-r--r-- | util/gss-tokens.c | 9 | ||||
-rw-r--r-- | util/gss-tokens.h | 44 | ||||
-rw-r--r-- | util/macros.h | 17 | ||||
-rw-r--r-- | util/messages.c | 4 | ||||
-rw-r--r-- | util/messages.h | 96 | ||||
-rw-r--r-- | util/network.c | 28 | ||||
-rw-r--r-- | util/network.h | 108 | ||||
-rw-r--r-- | util/protocol.h | 49 | ||||
-rw-r--r-- | util/tokens.c | 7 | ||||
-rw-r--r-- | util/tokens.h | 62 | ||||
-rw-r--r-- | util/util.h | 412 | ||||
-rw-r--r-- | util/vector.c | 3 | ||||
-rw-r--r-- | util/vector.h | 122 | ||||
-rw-r--r-- | util/xmalloc.c | 3 | ||||
-rw-r--r-- | util/xmalloc.h | 100 | ||||
-rw-r--r-- | util/xwrite.c | 2 | ||||
-rw-r--r-- | util/xwrite.h | 46 |
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 */ |