source: web/old/remctl-2.14/util/util.h @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 15.0 KB
Line 
1/*
2 * Utility functions.
3 *
4 * This is a variety of utility functions that are used internally by pieces
5 * of remctl.  Many of them came originally from INN.
6 *
7 * Written by Russ Allbery <rra@stanford.edu>
8 * Based on prior work by Anton Ushakov
9 * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008
10 *     Board of Trustees, Leland Stanford Jr. University
11 * Copyright (c) 2004, 2005, 2006, 2007
12 *     by Internet Systems Consortium, Inc. ("ISC")
13 * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
14 *     2002, 2003 by The Internet Software Consortium and Rich Salz
15 *
16 * See LICENSE for licensing terms.
17 */
18
19#ifndef UTIL_UTIL_H
20#define UTIL_UTIL_H 1
21
22#include <config.h>
23#include <portable/gssapi.h>
24#include <portable/macros.h>
25#include <portable/stdbool.h>
26
27#include <stdarg.h>
28#include <sys/types.h>
29
30/* Windows uses this for something else. */
31#ifdef _WIN32
32# undef ERROR_BAD_COMMAND
33#endif
34
35/* Used for unused parameters to silence gcc warnings. */
36#define UNUSED __attribute__((__unused__))
37
38BEGIN_DECLS
39
40/* Forward declarations to avoid includes. */
41struct addrinfo;
42struct iovec;
43struct sockaddr;
44
45/* Maximum lengths from the protocol specification of tokens and data. */
46#define TOKEN_MAX_LENGTH        (1024 * 1024)
47#define TOKEN_MAX_DATA          (64 * 1024)
48
49/* Failure return codes from token_send and token_recv. */
50enum token_status {
51    TOKEN_OK = 0,
52    TOKEN_FAIL_SYSTEM  = -1,    /* System call failed, error in errno */
53    TOKEN_FAIL_SOCKET  = -2,    /* Socket call failed, error in socket_errno */
54    TOKEN_FAIL_INVALID = -3,    /* Invalid token from remote site */
55    TOKEN_FAIL_LARGE   = -4,    /* Token data exceeds max length */
56    TOKEN_FAIL_EOF     = -5,    /* Unexpected end of file while reading */
57    TOKEN_FAIL_GSSAPI  = -6     /* GSS-API failure {en,de}crypting token */
58};
59
60/* Token types and flags. */
61enum token_flags {
62    TOKEN_NOOP          = (1 << 0),
63    TOKEN_CONTEXT       = (1 << 1),
64    TOKEN_DATA          = (1 << 2),
65    TOKEN_MIC           = (1 << 3),
66    TOKEN_CONTEXT_NEXT  = (1 << 4),
67    TOKEN_SEND_MIC      = (1 << 5),
68    TOKEN_PROTOCOL      = (1 << 6)
69};
70
71/* Message types. */
72enum message_types {
73    MESSAGE_COMMAND = 1,
74    MESSAGE_QUIT    = 2,
75    MESSAGE_OUTPUT  = 3,
76    MESSAGE_STATUS  = 4,
77    MESSAGE_ERROR   = 5,
78    MESSAGE_VERSION = 6
79};
80
81/* Error codes. */
82enum error_codes {
83    ERROR_INTERNAL        = 1,  /* Internal server failure. */
84    ERROR_BAD_TOKEN       = 2,  /* Invalid format in token. */
85    ERROR_UNKNOWN_MESSAGE = 3,  /* Unknown message type. */
86    ERROR_BAD_COMMAND     = 4,  /* Invalid command format in token. */
87    ERROR_UNKNOWN_COMMAND = 5,  /* Unknown command. */
88    ERROR_ACCESS          = 6,  /* Access denied. */
89    ERROR_TOOMANY_ARGS    = 7,  /* Argument count exceeds server limit. */
90    ERROR_TOOMUCH_DATA    = 8   /* Argument size exceeds server limit. */
91};
92
93/* Default to a hidden visibility for all util functions. */
94#pragma GCC visibility push(hidden)
95
96/*
97 * Sending and receiving tokens.  Do not use gss_release_buffer to free the
98 * token returned by token_recv; this will cause crashes on Windows.  Call
99 * free on the value member instead.
100 */
101enum token_status token_send(int fd, int flags, gss_buffer_t);
102enum token_status token_recv(int fd, int *flags, gss_buffer_t, size_t max);
103
104/*
105 * The same, but with a GSS-API protection layer applied.  On a GSS-API
106 * failure, the major and minor status are returned in the final two
107 * arguments.
108 */
109enum token_status token_send_priv(int fd, gss_ctx_id_t, int flags,
110                                  gss_buffer_t, OM_uint32 *, OM_uint32 *);
111enum token_status token_recv_priv(int fd, gss_ctx_id_t, int *flags,
112                                  gss_buffer_t, size_t max, OM_uint32 *,
113                                  OM_uint32 *);
114
115/*
116 * Convert a GSS-API error code pair into a human-readable string.  Returns a
117 * newly allocated string that the caller must free.
118 */
119char *gssapi_error_string(const char *prefix, OM_uint32, OM_uint32);
120
121/* Concatenate NULL-terminated strings into a newly allocated string. */
122char *concat(const char *first, ...);
123
124/*
125 * Given a base path and a file name, create a newly allocated path string.
126 * The name will be appended to base with a / between them.  Exceptionally, if
127 * name begins with a slash, it will be strdup'd and returned as-is.
128 */
129char *concatpath(const char *base, const char *name);
130
131/*
132 * Like the non-x versions of the same function, but keep writing until either
133 * the write is not making progress or there's a real error.  Handle partial
134 * writes and EINTR/EAGAIN errors.
135 */
136ssize_t xpwrite(int fd, const void *buffer, size_t size, off_t offset);
137ssize_t xwrite(int fd, const void *buffer, size_t size);
138ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt);
139
140/*
141 * Create a socket and bind it to the specified address and port (either IPv4
142 * or IPv6), returning the resulting file descriptor or -1 on error.  Errors
143 * are reported using warn/syswarn.  To bind to all interfaces, use "any" or
144 * "all" for address.
145 */
146int network_bind_ipv4(const char *address, unsigned short port);
147int network_bind_ipv6(const char *address, unsigned short port);
148
149/*
150 * Create and bind sockets for every local address (normally two, one for IPv4
151 * and one for IPv6, if IPv6 support is enabled).  If IPv6 is not enabled,
152 * just one socket will be created and bound to the IPv4 wildcard address.
153 * fds will be set to an array containing the resulting file descriptors, with
154 * count holding the count returned.
155 */
156void network_bind_all(unsigned short port, int **fds, int *count);
157
158/*
159 * Create a socket and connect it to the remote service given by the linked
160 * list of addrinfo structs.  Returns the new file descriptor on success and
161 * -1 on failure, with the error left in errno.  Takes an optional source
162 * address.
163 */
164int network_connect(struct addrinfo *, const char *source);
165
166/*
167 * Like network_connect but takes a host and port instead.  If host lookup
168 * fails, errno may not be set to anything useful.
169 */
170int network_connect_host(const char *host, unsigned short port,
171                         const char *source);
172
173/*
174 * Creates a socket of the specified domain and type and binds it to the
175 * appropriate source address, either the one supplied or the appropriate
176 * innconf setting if the provided source address is NULL.  To bind to all
177 * interfaces, use "all" for address.  Returns the newly created file
178 * descriptor or -1 on error.
179 *
180 * This is a lower-level function intended primarily for the use of clients
181 * that will then go on to do a non-blocking connect.
182 */
183int network_client_create(int domain, int type, const char *source);
184
185/*
186 * Put an ASCII representation of the address in a sockaddr into the provided
187 * buffer, which should hold at least INET6_ADDRSTRLEN characters.
188 */
189bool network_sockaddr_sprint(char *, size_t, const struct sockaddr *);
190
191/*
192 * Returns if the addresses from the two sockaddrs are equal.  The ports are
193 * ignored, and only AF_INET or AF_INET6 sockaddrs are supported (all others
194 * will return false).
195 */
196bool network_sockaddr_equal(const struct sockaddr *, const struct sockaddr *);
197
198/* Returns the port number from a sockaddr. */
199unsigned short network_sockaddr_port(const struct sockaddr *);
200
201/*
202 * Compare two addresses relative to an optional mask.  Returns true if
203 * they're equal, false otherwise or on a parse error.
204 */
205bool network_addr_match(const char *, const char *, const char *mask);
206
207/* Set a file descriptor close-on-exec or nonblocking. */
208bool fdflag_close_exec(int fd, bool flag);
209bool fdflag_nonblocking(int fd, bool flag);
210
211/*
212 * The reporting functions.  The ones prefaced by "sys" add a colon, a space,
213 * and the results of strerror(errno) to the output and are intended for
214 * reporting failures of system calls.
215 */
216void debug(const char *, ...)
217    __attribute__((__format__(printf, 1, 2)));
218void notice(const char *, ...)
219    __attribute__((__format__(printf, 1, 2)));
220void sysnotice(const char *, ...)
221    __attribute__((__format__(printf, 1, 2)));
222void warn(const char *, ...)
223    __attribute__((__format__(printf, 1, 2)));
224void syswarn(const char *, ...)
225    __attribute__((__format__(printf, 1, 2)));
226void die(const char *, ...)
227    __attribute__((__noreturn__, __format__(printf, 1, 2)));
228void sysdie(const char *, ...)
229    __attribute__((__noreturn__, __format__(printf, 1, 2)));
230
231/*
232 * Set the handlers for various message functions.  All of these functions
233 * take a count of the number of handlers and then function pointers for each
234 * of those handlers.  These functions are not thread-safe; they set global
235 * variables.
236 */
237void message_handlers_debug(int count, ...);
238void message_handlers_notice(int count, ...);
239void message_handlers_warn(int count, ...);
240void message_handlers_die(int count, ...);
241
242/*
243 * Some useful handlers, intended to be passed to message_handlers_*.  All
244 * handlers take the length of the formatted message, the format, a variadic
245 * argument list, and the errno setting if any.
246 */
247void message_log_stdout(int, const char *, va_list, int);
248void message_log_stderr(int, const char *, va_list, int);
249void message_log_syslog_debug(int, const char *, va_list, int);
250void message_log_syslog_info(int, const char *, va_list, int);
251void message_log_syslog_notice(int, const char *, va_list, int);
252void message_log_syslog_warning(int, const char *, va_list, int);
253void message_log_syslog_err(int, const char *, va_list, int);
254void message_log_syslog_crit(int, const char *, va_list, int);
255
256/* The type of a message handler. */
257typedef void (*message_handler_func)(int, const char *, va_list, int);
258
259/* If non-NULL, called before exit and its return value passed to exit. */
260extern int (*message_fatal_cleanup)(void);
261
262/*
263 * If non-NULL, prepended (followed by ": ") to all messages printed by either
264 * message_log_stdout or message_log_stderr.
265 */
266extern const char *message_program_name;
267
268struct vector {
269    size_t count;
270    size_t allocated;
271    char **strings;
272};
273
274struct cvector {
275    size_t count;
276    size_t allocated;
277    const char **strings;
278};
279
280/* Create a new, empty vector. */
281struct vector *vector_new(void);
282struct cvector *cvector_new(void);
283
284/* Add a string to a vector.  Resizes the vector if necessary. */
285void vector_add(struct vector *, const char *string);
286void cvector_add(struct cvector *, const char *string);
287
288/* Add a counted string to a vector.  Only available for vectors. */
289void vector_addn(struct vector *, const char *string, size_t length);
290
291/*
292 * Resize the array of strings to hold size entries.  Saves reallocation work
293 * in vector_add if it's known in advance how many entries there will be.
294 */
295void vector_resize(struct vector *, size_t size);
296void cvector_resize(struct cvector *, size_t size);
297
298/*
299 * Reset the number of elements to zero, freeing all of the strings for a
300 * regular vector, but not freeing the strings array (to cut down on memory
301 * allocations if the vector will be reused).
302 */
303void vector_clear(struct vector *);
304void cvector_clear(struct cvector *);
305
306/* Free the vector and all resources allocated for it. */
307void vector_free(struct vector *);
308void cvector_free(struct cvector *);
309
310/*
311 * Split functions build a vector from a string.  vector_split splits on a
312 * specified character, while vector_split_space splits on any sequence of
313 * spaces or tabs (not any sequence of whitespace, as just spaces or tabs is
314 * more useful).  The cvector versions destructively modify the provided
315 * string in-place to insert nul characters between the strings.  If the
316 * vector argument is NULL, a new vector is allocated; otherwise, the provided
317 * one is reused.
318 *
319 * Empty strings will yield zero-length vectors.  Adjacent delimiters are
320 * treated as a single delimiter by *_split_space, but *not* by *_split, so
321 * callers of *_split should be prepared for zero-length strings in the
322 * vector.
323 */
324struct vector *vector_split(const char *string, char sep, struct vector *);
325struct vector *vector_split_space(const char *string, struct vector *);
326struct cvector *cvector_split(char *string, char sep, struct cvector *);
327struct cvector *cvector_split_space(char *string, struct cvector *);
328
329/*
330 * Build a string from a vector by joining its components together with the
331 * specified string as separator.  Returns a newly allocated string; caller is
332 * responsible for freeing.
333 */
334char *vector_join(const struct vector *, const char *seperator);
335char *cvector_join(const struct cvector *, const char *separator);
336
337/*
338 * Exec the given program with the vector as its arguments.  Return behavior
339 * is the same as execv.  Note the argument order is different than the other
340 * vector functions (but the same as execv).
341 */
342int vector_exec(const char *path, struct vector *);
343int cvector_exec(const char *path, struct cvector *);
344
345/*
346 * The functions are actually macros so that we can pick up the file and line
347 * number information for debugging error messages without the user having to
348 * pass those in every time.
349 */
350#define xcalloc(n, size)        x_calloc((n), (size), __FILE__, __LINE__)
351#define xmalloc(size)           x_malloc((size), __FILE__, __LINE__)
352#define xrealloc(p, size)       x_realloc((p), (size), __FILE__, __LINE__)
353#define xstrdup(p)              x_strdup((p), __FILE__, __LINE__)
354#define xstrndup(p, size)       x_strndup((p), (size), __FILE__, __LINE__)
355#define xvasprintf(p, f, a)     x_vasprintf((p), (f), (a), __FILE__, __LINE__)
356
357/*
358 * asprintf is a special case since it takes variable arguments.  If we have
359 * support for variadic macros, we can still pass in the file and line and
360 * just need to put them somewhere else in the argument list than last.
361 * Otherwise, just call x_asprintf directly.  This means that the number of
362 * arguments x_asprintf takes must vary depending on whether variadic macros
363 * are supported.
364 */
365#ifdef HAVE_C99_VAMACROS
366# define xasprintf(p, f, ...) \
367    x_asprintf((p), __FILE__, __LINE__, (f), __VA_ARGS__)
368#elif HAVE_GNU_VAMACROS
369# define xasprintf(p, f, args...) \
370    x_asprintf((p), __FILE__, __LINE__, (f), args)
371#else
372# define xasprintf x_asprintf
373#endif
374
375/*
376 * Last two arguments are always file and line number.  These are internal
377 * implementations that should not be called directly.
378 */
379void *x_calloc(size_t, size_t, const char *, int);
380void *x_malloc(size_t, const char *, int);
381void *x_realloc(void *, size_t, const char *, int);
382char *x_strdup(const char *, const char *, int);
383char *x_strndup(const char *, size_t, const char *, int);
384int x_vasprintf(char **, const char *, va_list, const char *, int);
385
386/* asprintf special case. */
387#if HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS
388int x_asprintf(char **, const char *, int, const char *, ...);
389#else
390int x_asprintf(char **, const char *, ...);
391#endif
392
393/* Failure handler takes the function, the size, the file, and the line. */
394typedef void (*xmalloc_handler_type)(const char *, size_t, const char *, int);
395
396/* The default error handler. */
397void xmalloc_fail(const char *, size_t, const char *, int);
398
399/*
400 * Assign to this variable to choose a handler other than the default, which
401 * just calls sysdie.
402 */
403extern xmalloc_handler_type xmalloc_error_handler;
404
405/* Undo default visibility change. */
406#pragma GCC visibility pop
407
408END_DECLS
409
410#endif /* UTIL_UTIL_H */
Note: See TracBrowser for help on using the repository browser.