|
Packit |
fd8b60 |
/* -*- mode: c; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/* include/k5-platform.h */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright 2003, 2004, 2005, 2007, 2008, 2009 Massachusetts Institute of Technology.
|
|
Packit |
fd8b60 |
* All Rights Reserved.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Export of this software from the United States of America may
|
|
Packit |
fd8b60 |
* require a specific license from the United States Government.
|
|
Packit |
fd8b60 |
* It is the responsibility of any person or organization contemplating
|
|
Packit |
fd8b60 |
* export to obtain such a license before exporting.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
|
Packit |
fd8b60 |
* distribute this software and its documentation for any purpose and
|
|
Packit |
fd8b60 |
* without fee is hereby granted, provided that the above copyright
|
|
Packit |
fd8b60 |
* notice appear in all copies and that both that copyright notice and
|
|
Packit |
fd8b60 |
* this permission notice appear in supporting documentation, and that
|
|
Packit |
fd8b60 |
* the name of M.I.T. not be used in advertising or publicity pertaining
|
|
Packit |
fd8b60 |
* to distribution of the software without specific, written prior
|
|
Packit |
fd8b60 |
* permission. Furthermore if you modify this software you must label
|
|
Packit |
fd8b60 |
* your software as modified software and not distribute it in such a
|
|
Packit |
fd8b60 |
* fashion that it might be confused with the original M.I.T. software.
|
|
Packit |
fd8b60 |
* M.I.T. makes no representations about the suitability of
|
|
Packit |
fd8b60 |
* this software for any purpose. It is provided "as is" without express
|
|
Packit |
fd8b60 |
* or implied warranty.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Some platform-dependent definitions to sync up the C support level.
|
|
Packit |
fd8b60 |
* Some to a C99-ish level, some related utility code.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Currently:
|
|
Packit |
fd8b60 |
* + [u]int{8,16,32}_t types
|
|
Packit |
fd8b60 |
* + 64-bit types and load/store code
|
|
Packit |
fd8b60 |
* + SIZE_MAX
|
|
Packit |
fd8b60 |
* + shared library init/fini hooks
|
|
Packit |
fd8b60 |
* + consistent getpwnam/getpwuid interfaces
|
|
Packit |
fd8b60 |
* + va_copy fudged if not provided
|
|
Packit |
fd8b60 |
* + strlcpy/strlcat
|
|
Packit |
fd8b60 |
* + fnmatch
|
|
Packit |
fd8b60 |
* + [v]asprintf
|
|
Packit |
fd8b60 |
* + strerror_r
|
|
Packit |
fd8b60 |
* + mkstemp
|
|
Packit |
fd8b60 |
* + zap (support function and macro)
|
|
Packit |
fd8b60 |
* + constant time memory comparison
|
|
Packit |
fd8b60 |
* + path manipulation
|
|
Packit |
fd8b60 |
* + _, N_, dgettext, bindtextdomain (for localization)
|
|
Packit |
fd8b60 |
* + getopt_long
|
|
Packit |
fd8b60 |
* + secure_getenv
|
|
Packit |
fd8b60 |
* + fetching filenames from a directory
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef K5_PLATFORM_H
|
|
Packit |
fd8b60 |
#define K5_PLATFORM_H
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include "autoconf.h"
|
|
Packit |
fd8b60 |
#include <assert.h>
|
|
Packit |
fd8b60 |
#include <string.h>
|
|
Packit |
fd8b60 |
#include <stdarg.h>
|
|
Packit |
fd8b60 |
#include <stdint.h>
|
|
Packit |
fd8b60 |
#include <limits.h>
|
|
Packit |
fd8b60 |
#include <stdlib.h>
|
|
Packit |
fd8b60 |
#include <stdio.h>
|
|
Packit |
fd8b60 |
#include <fcntl.h>
|
|
Packit |
fd8b60 |
#include <errno.h>
|
|
Packit |
fd8b60 |
#ifdef HAVE_FNMATCH_H
|
|
Packit |
fd8b60 |
#include <fnmatch.h>
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
fd8b60 |
#include <unistd.h>
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifdef _WIN32
|
|
Packit |
fd8b60 |
#define CAN_COPY_VA_LIST
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* This attribute prevents unused function warnings in gcc and clang. */
|
|
Packit |
fd8b60 |
#ifdef __GNUC__
|
|
Packit |
fd8b60 |
#define UNUSED __attribute__((__unused__))
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
#define UNUSED
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
|
|
Packit |
fd8b60 |
#include <TargetConditionals.h>
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Initialization and finalization function support for libraries.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
At top level, before the functions are defined or even declared:
|
|
Packit |
fd8b60 |
MAKE_INIT_FUNCTION(init_fn);
|
|
Packit |
fd8b60 |
MAKE_FINI_FUNCTION(fini_fn);
|
|
Packit |
fd8b60 |
Then:
|
|
Packit |
fd8b60 |
int init_fn(void) { ... }
|
|
Packit |
fd8b60 |
void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... }
|
|
Packit |
fd8b60 |
In code, in the same file:
|
|
Packit |
fd8b60 |
err = CALL_INIT_FUNCTION(init_fn);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
To trigger or verify the initializer invocation from another file,
|
|
Packit |
fd8b60 |
a helper function must be created.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
This model handles both the load-time execution (Windows) and
|
|
Packit |
fd8b60 |
delayed execution (pthread_once) approaches, and should be able to
|
|
Packit |
fd8b60 |
guarantee in both cases that the init function is run once, in one
|
|
Packit |
fd8b60 |
thread, before other stuff in the library is done; furthermore, the
|
|
Packit |
fd8b60 |
finalization code should only run if the initialization code did.
|
|
Packit |
fd8b60 |
(Maybe I could've made the "if INITIALIZER_RAN" test implicit, via
|
|
Packit |
fd8b60 |
another function hidden in macros, but this is hairy enough
|
|
Packit |
fd8b60 |
already.)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
The init_fn and fini_fn names should be chosen such that any
|
|
Packit |
fd8b60 |
exported names staring with those names, and optionally followed by
|
|
Packit |
fd8b60 |
additional characters, fits in with any namespace constraints on
|
|
Packit |
fd8b60 |
the library in question.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
There's also PROGRAM_EXITING() currently always defined as zero.
|
|
Packit |
fd8b60 |
If there's some trivial way to find out if the fini function is
|
|
Packit |
fd8b60 |
being called because the program that the library is linked into is
|
|
Packit |
fd8b60 |
exiting, we can just skip all the work because the resources are
|
|
Packit |
fd8b60 |
about to be freed up anyways. Generally this is likely to be the
|
|
Packit |
fd8b60 |
same as distinguishing whether the library was loaded dynamically
|
|
Packit |
fd8b60 |
while the program was running, or loaded as part of program
|
|
Packit |
fd8b60 |
startup. On most platforms, I don't think we can distinguish these
|
|
Packit |
fd8b60 |
cases easily, and it's probably not worth expending any significant
|
|
Packit |
fd8b60 |
effort. (Note in particular that atexit() won't do, because if the
|
|
Packit |
fd8b60 |
library is explicitly loaded and unloaded, it would have to be able
|
|
Packit |
fd8b60 |
to deregister the atexit callback function. Also, the system limit
|
|
Packit |
fd8b60 |
on atexit callbacks may be small.)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
Implementation outline:
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that
|
|
Packit |
fd8b60 |
is sought at library build time, and code is added to invoke the
|
|
Packit |
fd8b60 |
function when the library is unloaded. MAKE_INIT_FUNCTION does
|
|
Packit |
fd8b60 |
likewise, but the function is invoked when the library is loaded,
|
|
Packit |
fd8b60 |
and an extra variable is declared to hold an error code and a "yes
|
|
Packit |
fd8b60 |
the initializer ran" flag. CALL_INIT_FUNCTION blows up if the flag
|
|
Packit |
fd8b60 |
isn't set, otherwise returns the error code.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a
|
|
Packit |
fd8b60 |
name derived from the function name, containing a k5_once_t
|
|
Packit |
fd8b60 |
(pthread_once_t or int), an error code, and a pointer to the
|
|
Packit |
fd8b60 |
function. The function itself is declared static, but the
|
|
Packit |
fd8b60 |
associated variable has external linkage. CALL_INIT_FUNCTION
|
|
Packit |
fd8b60 |
ensures thath the function is called exactly once (pthread_once or
|
|
Packit |
fd8b60 |
just check the flag) and returns the stored error code (or the
|
|
Packit |
fd8b60 |
pthread_once error).
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
(That's the basic idea. With some debugging assert() calls and
|
|
Packit |
fd8b60 |
such, it's a bit more complicated. And we also need to handle
|
|
Packit |
fd8b60 |
doing the pthread test at run time on systems where that works, so
|
|
Packit |
fd8b60 |
we use the k5_once_t stuff instead.)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
UNIX, with compiler support: MAKE_FINI_FUNCTION declares the
|
|
Packit |
fd8b60 |
function as a destructor, and the run time linker support or
|
|
Packit |
fd8b60 |
whatever will cause it to be invoked when the library is unloaded,
|
|
Packit |
fd8b60 |
the program ends, etc.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with
|
|
Packit |
fd8b60 |
a magic name that is sought at library build time, and linker
|
|
Packit |
fd8b60 |
options are used to mark it as a finalization function for the
|
|
Packit |
fd8b60 |
library. The symbol must be exported.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
UNIX, no library finalization support: The finalization function
|
|
Packit |
fd8b60 |
never runs, and we leak memory. Tough.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
DELAY_INITIALIZER will be defined by the configure script if we
|
|
Packit |
fd8b60 |
want to use k5_once instead of load-time initialization. That'll
|
|
Packit |
fd8b60 |
be the preferred method on most systems except Windows, where we
|
|
Packit |
fd8b60 |
have to initialize some mutexes.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
For maximum flexibility in defining the macros, the function name
|
|
Packit |
fd8b60 |
parameter should be a simple name, not even a macro defined as
|
|
Packit |
fd8b60 |
another name. The function should have a unique name, and should
|
|
Packit |
fd8b60 |
conform to whatever namespace is used by the library in question.
|
|
Packit |
fd8b60 |
(We do have export lists, but (1) they're not used for all
|
|
Packit |
fd8b60 |
platforms, and (2) they're not used for static libraries.)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
If the macro expansion needs the function to have been declared, it
|
|
Packit |
fd8b60 |
must include a declaration. If it is not necessary for the symbol
|
|
Packit |
fd8b60 |
name to be exported from the object file, the macro should declare
|
|
Packit |
fd8b60 |
it as "static". Hence the signature must exactly match "void
|
|
Packit |
fd8b60 |
foo(void)". (ANSI C allows a static declaration followed by a
|
|
Packit |
fd8b60 |
non-static one; the result is internal linkage.) The macro
|
|
Packit |
fd8b60 |
expansion has to come before the function, because gcc apparently
|
|
Packit |
fd8b60 |
won't act on "__attribute__((constructor))" if it comes after the
|
|
Packit |
fd8b60 |
function definition.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
This is going to be compiler- and environment-specific, and may
|
|
Packit |
fd8b60 |
require some support at library build time, and/or "asm"
|
|
Packit |
fd8b60 |
statements. But through macro expansion and auxiliary functions,
|
|
Packit |
fd8b60 |
we should be able to handle most things except #pragma.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
It's okay for this code to require that the library be built
|
|
Packit |
fd8b60 |
with the same compiler and compiler options throughout, but
|
|
Packit |
fd8b60 |
we shouldn't require that the library and application use the
|
|
Packit |
fd8b60 |
same compiler.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
For static libraries, we don't really care about cleanup too much,
|
|
Packit |
fd8b60 |
since it's all memory handling and mutex allocation which will all
|
|
Packit |
fd8b60 |
be cleaned up when the program exits. Thus, it's okay if gcc-built
|
|
Packit |
fd8b60 |
static libraries don't play nicely with cc-built executables when
|
|
Packit |
fd8b60 |
it comes to static constructors, just as long as it doesn't cause
|
|
Packit |
fd8b60 |
linking to fail.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
For dynamic libraries on UNIX, we'll use pthread_once-type support
|
|
Packit |
fd8b60 |
to do delayed initialization, so if finalization can't be made to
|
|
Packit |
fd8b60 |
work, we'll only have memory leaks in a load/use/unload cycle. If
|
|
Packit |
fd8b60 |
anyone (like, say, the OS vendor) complains about this, they can
|
|
Packit |
fd8b60 |
tell us how to get a shared library finalization function invoked
|
|
Packit |
fd8b60 |
automatically.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
Currently there's --disable-delayed-initialization for preventing
|
|
Packit |
fd8b60 |
the initialization from being delayed on UNIX, but that's mainly
|
|
Packit |
fd8b60 |
just for testing the linker options for initialization, and will
|
|
Packit |
fd8b60 |
probably be removed at some point. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Helper macros. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# define JOIN__2_2(A,B) A ## _ ## _ ## B
|
|
Packit |
fd8b60 |
# define JOIN__2(A,B) JOIN__2_2(A,B)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set,
|
|
Packit |
fd8b60 |
always provide a function by the expected name, even if we're
|
|
Packit |
fd8b60 |
delaying initialization. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if defined(DELAY_INITIALIZER)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Run the initialization code during program execution, at the latest
|
|
Packit |
fd8b60 |
possible moment. This means multiple threads may be active. */
|
|
Packit |
fd8b60 |
# include "k5-thread.h"
|
|
Packit |
fd8b60 |
typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t;
|
|
Packit |
fd8b60 |
# ifdef USE_LINKER_INIT_OPTION
|
|
Packit |
fd8b60 |
# define MAYBE_DUMMY_INIT(NAME) \
|
|
Packit |
fd8b60 |
void JOIN__2(NAME, auxinit) () { }
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
# define MAYBE_DUMMY_INIT(NAME)
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# ifdef __GNUC__
|
|
Packit |
fd8b60 |
/* Do it in macro form so we get the file/line of the invocation if
|
|
Packit |
fd8b60 |
the assertion fails. */
|
|
Packit |
fd8b60 |
# define k5_call_init_function(I) \
|
|
Packit |
fd8b60 |
(__extension__ ({ \
|
|
Packit |
fd8b60 |
k5_init_t *k5int_i = (I); \
|
|
Packit |
fd8b60 |
int k5int_err = k5_once(&k5int_i->once, k5int_i->fn); \
|
|
Packit |
fd8b60 |
(k5int_err \
|
|
Packit |
fd8b60 |
? k5int_err \
|
|
Packit |
fd8b60 |
: (assert(k5int_i->did_run != 0), k5int_i->error)); \
|
|
Packit |
fd8b60 |
}))
|
|
Packit |
fd8b60 |
# define MAYBE_DEFINE_CALLINIT_FUNCTION
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
# define MAYBE_DEFINE_CALLINIT_FUNCTION \
|
|
Packit |
fd8b60 |
static inline int k5_call_init_function(k5_init_t *i) \
|
|
Packit |
fd8b60 |
{ \
|
|
Packit |
fd8b60 |
int err; \
|
|
Packit |
fd8b60 |
err = k5_once(&i->once, i->fn); \
|
|
Packit |
fd8b60 |
if (err) \
|
|
Packit |
fd8b60 |
return err; \
|
|
Packit |
fd8b60 |
assert (i->did_run != 0); \
|
|
Packit |
fd8b60 |
return i->error; \
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# define MAKE_INIT_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
static int NAME(void); \
|
|
Packit |
fd8b60 |
MAYBE_DUMMY_INIT(NAME) \
|
|
Packit |
fd8b60 |
/* forward declaration for use in initializer */ \
|
|
Packit |
fd8b60 |
static void JOIN__2(NAME, aux) (void); \
|
|
Packit |
fd8b60 |
static k5_init_t JOIN__2(NAME, once) = \
|
|
Packit |
fd8b60 |
{ K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) }; \
|
|
Packit |
fd8b60 |
MAYBE_DEFINE_CALLINIT_FUNCTION \
|
|
Packit |
fd8b60 |
static void JOIN__2(NAME, aux) (void) \
|
|
Packit |
fd8b60 |
{ \
|
|
Packit |
fd8b60 |
JOIN__2(NAME, once).did_run = 1; \
|
|
Packit |
fd8b60 |
JOIN__2(NAME, once).error = NAME(); \
|
|
Packit |
fd8b60 |
} \
|
|
Packit |
fd8b60 |
/* so ';' following macro use won't get error */ \
|
|
Packit |
fd8b60 |
static int NAME(void)
|
|
Packit |
fd8b60 |
# define CALL_INIT_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
k5_call_init_function(& JOIN__2(NAME, once))
|
|
Packit |
fd8b60 |
/* This should be called in finalization only, so we shouldn't have
|
|
Packit |
fd8b60 |
multiple active threads mucking around in our library at this
|
|
Packit |
fd8b60 |
point. So ignore the once_t object and just look at the flag.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
XXX Could we have problems with memory coherence between processors
|
|
Packit |
fd8b60 |
if we don't invoke mutex/once routines? Probably not, the
|
|
Packit |
fd8b60 |
application code should already be coordinating things such that
|
|
Packit |
fd8b60 |
the library code is not in use by this point, and memory
|
|
Packit |
fd8b60 |
synchronization will be needed there. */
|
|
Packit |
fd8b60 |
# define INITIALIZER_RAN(NAME) \
|
|
Packit |
fd8b60 |
(JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# define PROGRAM_EXITING() (0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Run initializer at load time, via GCC/C++ hook magic. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# ifdef USE_LINKER_INIT_OPTION
|
|
Packit |
fd8b60 |
/* Both gcc and linker option?? Favor gcc. */
|
|
Packit |
fd8b60 |
# define MAYBE_DUMMY_INIT(NAME) \
|
|
Packit |
fd8b60 |
void JOIN__2(NAME, auxinit) () { }
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
# define MAYBE_DUMMY_INIT(NAME)
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
typedef struct { int error; unsigned char did_run; } k5_init_t;
|
|
Packit |
fd8b60 |
# define MAKE_INIT_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
MAYBE_DUMMY_INIT(NAME) \
|
|
Packit |
fd8b60 |
static k5_init_t JOIN__2(NAME, ran) \
|
|
Packit |
fd8b60 |
= { 0, 2 }; \
|
|
Packit |
fd8b60 |
static void JOIN__2(NAME, aux)(void) \
|
|
Packit |
fd8b60 |
__attribute__((constructor)); \
|
|
Packit |
fd8b60 |
static int NAME(void); \
|
|
Packit |
fd8b60 |
static void JOIN__2(NAME, aux)(void) \
|
|
Packit |
fd8b60 |
{ \
|
|
Packit |
fd8b60 |
JOIN__2(NAME, ran).error = NAME(); \
|
|
Packit |
fd8b60 |
JOIN__2(NAME, ran).did_run = 3; \
|
|
Packit |
fd8b60 |
} \
|
|
Packit |
fd8b60 |
static int NAME(void)
|
|
Packit |
fd8b60 |
# define CALL_INIT_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
(JOIN__2(NAME, ran).did_run == 3 \
|
|
Packit |
fd8b60 |
? JOIN__2(NAME, ran).error \
|
|
Packit |
fd8b60 |
: (abort(),0))
|
|
Packit |
fd8b60 |
# define INITIALIZER_RAN(NAME) (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# define PROGRAM_EXITING() (0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Run initializer at load time, via linker magic, or in the
|
|
Packit |
fd8b60 |
case of WIN32, win_glue.c hard-coded knowledge. */
|
|
Packit |
fd8b60 |
typedef struct { int error; unsigned char did_run; } k5_init_t;
|
|
Packit |
fd8b60 |
# define MAKE_INIT_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
static k5_init_t JOIN__2(NAME, ran) \
|
|
Packit |
fd8b60 |
= { 0, 2 }; \
|
|
Packit |
fd8b60 |
static int NAME(void); \
|
|
Packit |
fd8b60 |
void JOIN__2(NAME, auxinit)() \
|
|
Packit |
fd8b60 |
{ \
|
|
Packit |
fd8b60 |
JOIN__2(NAME, ran).error = NAME(); \
|
|
Packit |
fd8b60 |
JOIN__2(NAME, ran).did_run = 3; \
|
|
Packit |
fd8b60 |
} \
|
|
Packit |
fd8b60 |
static int NAME(void)
|
|
Packit |
fd8b60 |
# define CALL_INIT_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
(JOIN__2(NAME, ran).did_run == 3 \
|
|
Packit |
fd8b60 |
? JOIN__2(NAME, ran).error \
|
|
Packit |
fd8b60 |
: (abort(),0))
|
|
Packit |
fd8b60 |
# define INITIALIZER_RAN(NAME) \
|
|
Packit |
fd8b60 |
(JOIN__2(NAME, ran).error == 0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# define PROGRAM_EXITING() (0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# error "Don't know how to do load-time initializers for this configuration."
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# define PROGRAM_EXITING() (0)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32)
|
|
Packit |
fd8b60 |
/* If we're told the linker option will be used, it doesn't really
|
|
Packit |
fd8b60 |
matter what compiler we're using. Do it the same way
|
|
Packit |
fd8b60 |
regardless. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# ifdef __hpux
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* On HP-UX, we need this auxiliary function. At dynamic load or
|
|
Packit |
fd8b60 |
unload time (but *not* program startup and termination for
|
|
Packit |
fd8b60 |
link-time specified libraries), the linker-indicated function
|
|
Packit |
fd8b60 |
is called with a handle on the library and a flag indicating
|
|
Packit |
fd8b60 |
whether it's being loaded or unloaded.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
The "real" fini function doesn't need to be exported, so
|
|
Packit |
fd8b60 |
declare it static.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
As usual, the final declaration is just for syntactic
|
|
Packit |
fd8b60 |
convenience, so the top-level invocation of this macro can be
|
|
Packit |
fd8b60 |
followed by a semicolon. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# include <dl.h>
|
|
Packit |
fd8b60 |
# define MAKE_FINI_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
static void NAME(void); \
|
|
Packit |
fd8b60 |
void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \
|
|
Packit |
fd8b60 |
void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \
|
|
Packit |
fd8b60 |
static void NAME(void)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# else /* not hpux */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# define MAKE_FINI_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
void NAME(void)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#elif !defined(SHARED)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* In this case, we just don't care about finalization. The code will still
|
|
Packit |
fd8b60 |
* define the function, but we won't do anything with it.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
# define MAKE_FINI_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
static void NAME(void) UNUSED
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS)
|
|
Packit |
fd8b60 |
/* If we're using gcc, if the C++ support works, the compiler should
|
|
Packit |
fd8b60 |
build executables and shared libraries that support the use of
|
|
Packit |
fd8b60 |
static constructors and destructors. The C compiler supports a
|
|
Packit |
fd8b60 |
function attribute that makes use of the same facility as C++.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
XXX How do we know if the C++ support actually works? */
|
|
Packit |
fd8b60 |
# define MAKE_FINI_FUNCTION(NAME) \
|
|
Packit |
fd8b60 |
static void NAME(void) __attribute__((destructor))
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
# error "Don't know how to do unload-time finalization for this configuration."
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef SIZE_MAX
|
|
Packit |
fd8b60 |
# define SIZE_MAX ((size_t)((size_t)0 - 1))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifdef _WIN32
|
|
Packit |
fd8b60 |
# define SSIZE_MAX ((ssize_t)(SIZE_MAX/2))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read and write integer values as (unaligned) octet strings in
|
|
Packit |
fd8b60 |
specific byte orders. Add per-platform optimizations as
|
|
Packit |
fd8b60 |
needed. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if HAVE_ENDIAN_H
|
|
Packit |
fd8b60 |
# include <endian.h>
|
|
Packit |
fd8b60 |
#elif HAVE_MACHINE_ENDIAN_H
|
|
Packit |
fd8b60 |
# include <machine/endian.h>
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
/* Check for BIG/LITTLE_ENDIAN macros. If exactly one is defined, use
|
|
Packit |
fd8b60 |
it. If both are defined, then BYTE_ORDER should be defined and
|
|
Packit |
fd8b60 |
match one of them. Try those symbols, then try again with an
|
|
Packit |
fd8b60 |
underscore prefix. */
|
|
Packit |
fd8b60 |
#if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
|
|
Packit |
fd8b60 |
# if BYTE_ORDER == BIG_ENDIAN
|
|
Packit |
fd8b60 |
# define K5_BE
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# if BYTE_ORDER == LITTLE_ENDIAN
|
|
Packit |
fd8b60 |
# define K5_LE
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#elif defined(BIG_ENDIAN)
|
|
Packit |
fd8b60 |
# define K5_BE
|
|
Packit |
fd8b60 |
#elif defined(LITTLE_ENDIAN)
|
|
Packit |
fd8b60 |
# define K5_LE
|
|
Packit |
fd8b60 |
#elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
|
|
Packit |
fd8b60 |
# if _BYTE_ORDER == _BIG_ENDIAN
|
|
Packit |
fd8b60 |
# define K5_BE
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# if _BYTE_ORDER == _LITTLE_ENDIAN
|
|
Packit |
fd8b60 |
# define K5_LE
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#elif defined(_BIG_ENDIAN)
|
|
Packit |
fd8b60 |
# define K5_BE
|
|
Packit |
fd8b60 |
#elif defined(_LITTLE_ENDIAN)
|
|
Packit |
fd8b60 |
# define K5_LE
|
|
Packit |
fd8b60 |
#elif defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
|
|
Packit |
fd8b60 |
# define K5_BE
|
|
Packit |
fd8b60 |
#elif defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
|
|
Packit |
fd8b60 |
# define K5_LE
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
#if !defined(K5_BE) && !defined(K5_LE)
|
|
Packit |
fd8b60 |
/* Look for some architectures we know about.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
MIPS can use either byte order, but the preprocessor tells us which
|
|
Packit |
fd8b60 |
mode we're compiling for. The GCC config files indicate that
|
|
Packit |
fd8b60 |
variants of Alpha and IA64 might be out there with both byte
|
|
Packit |
fd8b60 |
orders, but until we encounter the "wrong" ones in the real world,
|
|
Packit |
fd8b60 |
just go with the default (unless there are cpp predefines to help
|
|
Packit |
fd8b60 |
us there too).
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
As far as I know, only PDP11 and ARM (which we don't handle here)
|
|
Packit |
fd8b60 |
have strange byte orders where an 8-byte value isn't laid out as
|
|
Packit |
fd8b60 |
either 12345678 or 87654321. */
|
|
Packit |
fd8b60 |
# if defined(__i386__) || defined(_MIPSEL) || defined(__alpha__) || (defined(__ia64__) && !defined(__hpux))
|
|
Packit |
fd8b60 |
# define K5_LE
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# if defined(__hppa__) || defined(__rs6000__) || defined(__sparc__) || defined(_MIPSEB) || defined(__m68k__) || defined(__sparc64__) || defined(__ppc__) || defined(__ppc64__) || (defined(__hpux) && defined(__ia64__))
|
|
Packit |
fd8b60 |
# define K5_BE
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
#if defined(K5_BE) && defined(K5_LE)
|
|
Packit |
fd8b60 |
# error "oops, check the byte order macros"
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Optimize for GCC on platforms with known byte orders.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
GCC's packed structures can be written to with any alignment; the
|
|
Packit |
fd8b60 |
compiler will use byte operations, unaligned-word operations, or
|
|
Packit |
fd8b60 |
normal memory ops as appropriate for the architecture.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
This assumes the availability of uint##_t types, which should work
|
|
Packit |
fd8b60 |
on most of our platforms except Windows, where we're not using
|
|
Packit |
fd8b60 |
GCC. */
|
|
Packit |
fd8b60 |
#ifdef __GNUC__
|
|
Packit |
fd8b60 |
# define PUT(SIZE,PTR,VAL) (((struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i = (VAL))
|
|
Packit |
fd8b60 |
# define GET(SIZE,PTR) (((const struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i)
|
|
Packit |
fd8b60 |
# define PUTSWAPPED(SIZE,PTR,VAL) PUT(SIZE,PTR,SWAP##SIZE(VAL))
|
|
Packit |
fd8b60 |
# define GETSWAPPED(SIZE,PTR) SWAP##SIZE(GET(SIZE,PTR))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
/* To do: Define SWAP16, SWAP32, SWAP64 macros to byte-swap values
|
|
Packit |
fd8b60 |
with the indicated numbers of bits.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
Linux: byteswap.h, bswap_16 etc.
|
|
Packit |
fd8b60 |
Solaris 10: none
|
|
Packit |
fd8b60 |
macOS: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong}
|
|
Packit |
fd8b60 |
NetBSD: sys/bswap.h, bswap16 etc. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16)
|
|
Packit |
fd8b60 |
# include <byteswap.h>
|
|
Packit |
fd8b60 |
# define SWAP16 bswap_16
|
|
Packit |
fd8b60 |
# define SWAP32 bswap_32
|
|
Packit |
fd8b60 |
# ifdef HAVE_BSWAP_64
|
|
Packit |
fd8b60 |
# define SWAP64 bswap_64
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#elif TARGET_OS_MAC
|
|
Packit |
fd8b60 |
# include <architecture/byte_order.h>
|
|
Packit |
fd8b60 |
# define SWAP16 k5_swap16
|
|
Packit |
fd8b60 |
static inline unsigned int k5_swap16 (unsigned int x) {
|
|
Packit |
fd8b60 |
x &= 0xffff;
|
|
Packit |
fd8b60 |
return (x >> 8) | ((x & 0xff) << 8);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
# define SWAP32 OSSwapInt32
|
|
Packit |
fd8b60 |
# define SWAP64 OSSwapInt64
|
|
Packit |
fd8b60 |
#elif defined(HAVE_SYS_BSWAP_H)
|
|
Packit |
fd8b60 |
/* XXX NetBSD/x86 5.0.1 defines bswap16 and bswap32 as inline
|
|
Packit |
fd8b60 |
functions only, so autoconf doesn't pick up on their existence.
|
|
Packit |
fd8b60 |
So, no feature macro test for them here. The 64-bit version isn't
|
|
Packit |
fd8b60 |
inline at all, though, for whatever reason. */
|
|
Packit |
fd8b60 |
# include <sys/bswap.h>
|
|
Packit |
fd8b60 |
# define SWAP16 bswap16
|
|
Packit |
fd8b60 |
# define SWAP32 bswap32
|
|
Packit |
fd8b60 |
/* However, bswap64 causes lots of warnings about 'long long'
|
|
Packit |
fd8b60 |
constants; probably only on 32-bit platforms. */
|
|
Packit |
fd8b60 |
# if LONG_MAX > 0x7fffffffL
|
|
Packit |
fd8b60 |
# define SWAP64 bswap64
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Note that on Windows at least this file can be included from C++
|
|
Packit |
fd8b60 |
source, so casts *from* void* are required. */
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_16_be (unsigned int val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *p = (unsigned char *) vp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUT(16,p,val);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUTSWAPPED(16,p,val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
p[0] = (val >> 8) & 0xff;
|
|
Packit |
fd8b60 |
p[1] = (val ) & 0xff;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_32_be (unsigned int val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *p = (unsigned char *) vp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUT(32,p,val);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUTSWAPPED(32,p,val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
p[0] = (val >> 24) & 0xff;
|
|
Packit |
fd8b60 |
p[1] = (val >> 16) & 0xff;
|
|
Packit |
fd8b60 |
p[2] = (val >> 8) & 0xff;
|
|
Packit |
fd8b60 |
p[3] = (val ) & 0xff;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_64_be (uint64_t val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *p = (unsigned char *) vp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUT(64,p,val);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUTSWAPPED(64,p,val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
p[0] = (unsigned char)((val >> 56) & 0xff);
|
|
Packit |
fd8b60 |
p[1] = (unsigned char)((val >> 48) & 0xff);
|
|
Packit |
fd8b60 |
p[2] = (unsigned char)((val >> 40) & 0xff);
|
|
Packit |
fd8b60 |
p[3] = (unsigned char)((val >> 32) & 0xff);
|
|
Packit |
fd8b60 |
p[4] = (unsigned char)((val >> 24) & 0xff);
|
|
Packit |
fd8b60 |
p[5] = (unsigned char)((val >> 16) & 0xff);
|
|
Packit |
fd8b60 |
p[6] = (unsigned char)((val >> 8) & 0xff);
|
|
Packit |
fd8b60 |
p[7] = (unsigned char)((val ) & 0xff);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline unsigned short
|
|
Packit |
fd8b60 |
load_16_be (const void *cvp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const unsigned char *p = (const unsigned char *) cvp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GET(16,p);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GETSWAPPED(16,p);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return (p[1] | (p[0] << 8));
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline unsigned int
|
|
Packit |
fd8b60 |
load_32_be (const void *cvp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const unsigned char *p = (const unsigned char *) cvp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GET(32,p);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GETSWAPPED(32,p);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return (p[3] | (p[2] << 8)
|
|
Packit |
fd8b60 |
| ((uint32_t) p[1] << 16)
|
|
Packit |
fd8b60 |
| ((uint32_t) p[0] << 24));
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline uint64_t
|
|
Packit |
fd8b60 |
load_64_be (const void *cvp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const unsigned char *p = (const unsigned char *) cvp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GET(64,p);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GETSWAPPED(64,p);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return ((uint64_t)load_32_be(p) << 32) | load_32_be(p+4);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_16_le (unsigned int val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *p = (unsigned char *) vp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUT(16,p,val);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUTSWAPPED(16,p,val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
p[1] = (val >> 8) & 0xff;
|
|
Packit |
fd8b60 |
p[0] = (val ) & 0xff;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_32_le (unsigned int val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *p = (unsigned char *) vp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUT(32,p,val);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUTSWAPPED(32,p,val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
p[3] = (val >> 24) & 0xff;
|
|
Packit |
fd8b60 |
p[2] = (val >> 16) & 0xff;
|
|
Packit |
fd8b60 |
p[1] = (val >> 8) & 0xff;
|
|
Packit |
fd8b60 |
p[0] = (val ) & 0xff;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_64_le (uint64_t val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *p = (unsigned char *) vp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUT(64,p,val);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
PUTSWAPPED(64,p,val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
p[7] = (unsigned char)((val >> 56) & 0xff);
|
|
Packit |
fd8b60 |
p[6] = (unsigned char)((val >> 48) & 0xff);
|
|
Packit |
fd8b60 |
p[5] = (unsigned char)((val >> 40) & 0xff);
|
|
Packit |
fd8b60 |
p[4] = (unsigned char)((val >> 32) & 0xff);
|
|
Packit |
fd8b60 |
p[3] = (unsigned char)((val >> 24) & 0xff);
|
|
Packit |
fd8b60 |
p[2] = (unsigned char)((val >> 16) & 0xff);
|
|
Packit |
fd8b60 |
p[1] = (unsigned char)((val >> 8) & 0xff);
|
|
Packit |
fd8b60 |
p[0] = (unsigned char)((val ) & 0xff);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline unsigned short
|
|
Packit |
fd8b60 |
load_16_le (const void *cvp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const unsigned char *p = (const unsigned char *) cvp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GET(16,p);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GETSWAPPED(16,p);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return (p[0] | (p[1] << 8));
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline unsigned int
|
|
Packit |
fd8b60 |
load_32_le (const void *cvp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const unsigned char *p = (const unsigned char *) cvp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GET(32,p);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GETSWAPPED(32,p);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline uint64_t
|
|
Packit |
fd8b60 |
load_64_le (const void *cvp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const unsigned char *p = (const unsigned char *) cvp;
|
|
Packit |
fd8b60 |
#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GET(64,p);
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
|
|
Packit |
fd8b60 |
return GETSWAPPED(64,p);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return ((uint64_t)load_32_le(p+4) << 32) | load_32_le(p);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define UINT16_TYPE uint16_t
|
|
Packit |
fd8b60 |
#define UINT32_TYPE uint32_t
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_16_n (unsigned int val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
UINT16_TYPE n = val;
|
|
Packit |
fd8b60 |
memcpy(vp, &n, 2);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_32_n (unsigned int val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
UINT32_TYPE n = val;
|
|
Packit |
fd8b60 |
memcpy(vp, &n, 4);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
store_64_n (uint64_t val, void *vp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
uint64_t n = val;
|
|
Packit |
fd8b60 |
memcpy(vp, &n, 8);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline unsigned short
|
|
Packit |
fd8b60 |
load_16_n (const void *p)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
UINT16_TYPE n;
|
|
Packit |
fd8b60 |
memcpy(&n, p, 2);
|
|
Packit |
fd8b60 |
return n;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline unsigned int
|
|
Packit |
fd8b60 |
load_32_n (const void *p)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
UINT32_TYPE n;
|
|
Packit |
fd8b60 |
memcpy(&n, p, 4);
|
|
Packit |
fd8b60 |
return n;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline uint64_t
|
|
Packit |
fd8b60 |
load_64_n (const void *p)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
uint64_t n;
|
|
Packit |
fd8b60 |
memcpy(&n, p, 8);
|
|
Packit |
fd8b60 |
return n;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#undef UINT16_TYPE
|
|
Packit |
fd8b60 |
#undef UINT32_TYPE
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Assume for simplicity that these swaps are identical. */
|
|
Packit |
fd8b60 |
static inline uint64_t
|
|
Packit |
fd8b60 |
k5_htonll (uint64_t val)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
#ifdef K5_BE
|
|
Packit |
fd8b60 |
return val;
|
|
Packit |
fd8b60 |
#elif defined K5_LE && defined SWAP64
|
|
Packit |
fd8b60 |
return SWAP64 (val);
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
return load_64_be ((unsigned char *)&val;;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline uint64_t
|
|
Packit |
fd8b60 |
k5_ntohll (uint64_t val)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return k5_htonll (val);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Make the interfaces to getpwnam and getpwuid consistent.
|
|
Packit |
fd8b60 |
Model the wrappers on the POSIX thread-safe versions, but
|
|
Packit |
fd8b60 |
use the unsafe system versions if the safe ones don't exist
|
|
Packit |
fd8b60 |
or we can't figure out their interfaces. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* int k5_getpwnam_r(const char *, blah blah) */
|
|
Packit |
fd8b60 |
#ifdef HAVE_GETPWNAM_R
|
|
Packit |
fd8b60 |
# ifndef GETPWNAM_R_4_ARGS
|
|
Packit |
fd8b60 |
/* POSIX */
|
|
Packit |
fd8b60 |
# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(getpwnam_r(NAME,REC,BUF,BUFSIZE,OUT) == 0 \
|
|
Packit |
fd8b60 |
? (*(OUT) == NULL ? -1 : 0) : -1)
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
/* POSIX drafts? */
|
|
Packit |
fd8b60 |
# ifdef GETPWNAM_R_RETURNS_INT
|
|
Packit |
fd8b60 |
# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(getpwnam_r(NAME,REC,BUF,BUFSIZE) == 0 \
|
|
Packit |
fd8b60 |
? (*(OUT) = REC, 0) \
|
|
Packit |
fd8b60 |
: (*(OUT) = NULL, -1))
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#else /* no getpwnam_r, or can't figure out #args or return type */
|
|
Packit |
fd8b60 |
/* Will get warnings about unused variables. */
|
|
Packit |
fd8b60 |
# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(*(OUT) = getpwnam(NAME), *(OUT) == NULL ? -1 : 0)
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* int k5_getpwuid_r(uid_t, blah blah) */
|
|
Packit |
fd8b60 |
#ifdef HAVE_GETPWUID_R
|
|
Packit |
fd8b60 |
# ifndef GETPWUID_R_4_ARGS
|
|
Packit |
fd8b60 |
/* POSIX */
|
|
Packit |
fd8b60 |
# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(getpwuid_r(UID,REC,BUF,BUFSIZE,OUT) == 0 \
|
|
Packit |
fd8b60 |
? (*(OUT) == NULL ? -1 : 0) : -1)
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
/* POSIX drafts? Yes, I mean to test GETPWNAM... here. Less junk to
|
|
Packit |
fd8b60 |
do at configure time. */
|
|
Packit |
fd8b60 |
# ifdef GETPWNAM_R_RETURNS_INT
|
|
Packit |
fd8b60 |
# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(getpwuid_r(UID,REC,BUF,BUFSIZE) == 0 \
|
|
Packit |
fd8b60 |
? (*(OUT) = REC, 0) \
|
|
Packit |
fd8b60 |
: (*(OUT) = NULL, -1))
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#else /* no getpwuid_r, or can't figure out #args or return type */
|
|
Packit |
fd8b60 |
/* Will get warnings about unused variables. */
|
|
Packit |
fd8b60 |
# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
|
|
Packit |
fd8b60 |
(*(OUT) = getpwuid(UID), *(OUT) == NULL ? -1 : 0)
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Ensure, if possible, that the indicated file descriptor won't be
|
|
Packit |
fd8b60 |
kept open if we exec another process (e.g., launching a ccapi
|
|
Packit |
fd8b60 |
server). If we don't know how to do it... well, just go about our
|
|
Packit |
fd8b60 |
business. Probably most callers won't check the return status
|
|
Packit |
fd8b60 |
anyways. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Macros make the Sun compiler happier, and all variants of this do a
|
|
Packit |
fd8b60 |
single evaluation of the argument, and fcntl and fileno should
|
|
Packit |
fd8b60 |
produce reasonable error messages on type mismatches, on any system
|
|
Packit |
fd8b60 |
with F_SETFD. */
|
|
Packit |
fd8b60 |
#ifdef F_SETFD
|
|
Packit |
fd8b60 |
# ifdef FD_CLOEXEC
|
|
Packit |
fd8b60 |
# define set_cloexec_fd(FD) ((void)fcntl((FD), F_SETFD, FD_CLOEXEC))
|
|
Packit |
fd8b60 |
# else
|
|
Packit |
fd8b60 |
# define set_cloexec_fd(FD) ((void)fcntl((FD), F_SETFD, 1))
|
|
Packit |
fd8b60 |
# endif
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
# define set_cloexec_fd(FD) ((void)(FD))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
#define set_cloexec_file(F) set_cloexec_fd(fileno(F))
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Since the original ANSI C spec left it undefined whether or
|
|
Packit |
fd8b60 |
how you could copy around a va_list, C 99 added va_copy.
|
|
Packit |
fd8b60 |
For old implementations, let's do our best to fake it.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
XXX Doesn't yet handle implementations with __va_copy (early draft)
|
|
Packit |
fd8b60 |
or GCC's __builtin_va_copy. */
|
|
Packit |
fd8b60 |
#if defined(HAS_VA_COPY) || defined(va_copy)
|
|
Packit |
fd8b60 |
/* Do nothing. */
|
|
Packit |
fd8b60 |
#elif defined(CAN_COPY_VA_LIST)
|
|
Packit |
fd8b60 |
#define va_copy(dest, src) ((dest) = (src))
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
/* Assume array type, but still simply copyable.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
There is, theoretically, the possibility that va_start will
|
|
Packit |
fd8b60 |
allocate some storage pointed to by the va_list, and in that case
|
|
Packit |
fd8b60 |
we'll just lose. If anyone cares, we could try to devise a test
|
|
Packit |
fd8b60 |
for that case. */
|
|
Packit |
fd8b60 |
#define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Provide strlcpy/strlcat interfaces. */
|
|
Packit |
fd8b60 |
#ifndef HAVE_STRLCPY
|
|
Packit |
fd8b60 |
#define strlcpy krb5int_strlcpy
|
|
Packit |
fd8b60 |
#define strlcat krb5int_strlcat
|
|
Packit |
fd8b60 |
extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz);
|
|
Packit |
fd8b60 |
extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Provide fnmatch interface. */
|
|
Packit |
fd8b60 |
#ifndef HAVE_FNMATCH
|
|
Packit |
fd8b60 |
#define fnmatch k5_fnmatch
|
|
Packit |
fd8b60 |
int k5_fnmatch(const char *pattern, const char *string, int flags);
|
|
Packit |
fd8b60 |
#define FNM_NOMATCH 1 /* Match failed. */
|
|
Packit |
fd8b60 |
#define FNM_NOSYS 2 /* Function not implemented. */
|
|
Packit |
fd8b60 |
#define FNM_NORES 3 /* Out of resources */
|
|
Packit |
fd8b60 |
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
|
|
Packit |
fd8b60 |
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
|
|
Packit |
fd8b60 |
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
|
|
Packit |
fd8b60 |
#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */
|
|
Packit |
fd8b60 |
#define FNM_LEADING_DIR 0x10 /* Ignore /<tail> after Imatch. */
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Provide [v]asprintf interfaces. */
|
|
Packit |
fd8b60 |
#ifndef HAVE_VSNPRINTF
|
|
Packit |
fd8b60 |
#ifdef _WIN32
|
|
Packit |
fd8b60 |
static inline int
|
|
Packit |
fd8b60 |
vsnprintf(char *str, size_t size, const char *format, va_list args)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
va_list args_copy;
|
|
Packit |
fd8b60 |
int length;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
va_copy(args_copy, args);
|
|
Packit |
fd8b60 |
length = _vscprintf(format, args_copy);
|
|
Packit |
fd8b60 |
va_end(args_copy);
|
|
Packit |
fd8b60 |
if (size > 0) {
|
|
Packit |
fd8b60 |
_vsnprintf(str, size, format, args);
|
|
Packit |
fd8b60 |
str[size - 1] = '\0';
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return length;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
static inline int
|
|
Packit |
fd8b60 |
snprintf(char *str, size_t size, const char *format, ...)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
va_list args;
|
|
Packit |
fd8b60 |
int n;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
va_start(args, format);
|
|
Packit |
fd8b60 |
n = vsnprintf(str, size, format, args);
|
|
Packit |
fd8b60 |
va_end(args);
|
|
Packit |
fd8b60 |
return n;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#else /* not win32 */
|
|
Packit |
fd8b60 |
#error We need an implementation of vsnprintf.
|
|
Packit |
fd8b60 |
#endif /* win32? */
|
|
Packit |
fd8b60 |
#endif /* no vsnprintf */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef HAVE_VASPRINTF
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
extern int krb5int_vasprintf(char **, const char *, va_list)
|
|
Packit |
fd8b60 |
#if !defined(__cplusplus) && (__GNUC__ > 2)
|
|
Packit |
fd8b60 |
__attribute__((__format__(__printf__, 2, 0)))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
;
|
|
Packit |
fd8b60 |
extern int krb5int_asprintf(char **, const char *, ...)
|
|
Packit |
fd8b60 |
#if !defined(__cplusplus) && (__GNUC__ > 2)
|
|
Packit |
fd8b60 |
__attribute__((__format__(__printf__, 2, 3)))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define vasprintf krb5int_vasprintf
|
|
Packit |
fd8b60 |
/* Assume HAVE_ASPRINTF iff HAVE_VASPRINTF. */
|
|
Packit |
fd8b60 |
#define asprintf krb5int_asprintf
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#elif defined(NEED_VASPRINTF_PROTO)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
extern int vasprintf(char **, const char *, va_list)
|
|
Packit |
fd8b60 |
#if !defined(__cplusplus) && (__GNUC__ > 2)
|
|
Packit |
fd8b60 |
__attribute__((__format__(__printf__, 2, 0)))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
;
|
|
Packit |
fd8b60 |
extern int asprintf(char **, const char *, ...)
|
|
Packit |
fd8b60 |
#if !defined(__cplusplus) && (__GNUC__ > 2)
|
|
Packit |
fd8b60 |
__attribute__((__format__(__printf__, 2, 3)))
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#endif /* have vasprintf and prototype? */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Return true if the snprintf return value RESULT reflects a buffer
|
|
Packit |
fd8b60 |
overflow for the buffer size SIZE.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
We cast the result to unsigned int for two reasons. First, old
|
|
Packit |
fd8b60 |
implementations of snprintf (such as the one in Solaris 9 and
|
|
Packit |
fd8b60 |
prior) return -1 on a buffer overflow. Casting the result to -1
|
|
Packit |
fd8b60 |
will convert that value to UINT_MAX, which should compare larger
|
|
Packit |
fd8b60 |
than any reasonable buffer size. Second, comparing signed and
|
|
Packit |
fd8b60 |
unsigned integers will generate warnings with some compilers, and
|
|
Packit |
fd8b60 |
can have unpredictable results, particularly when the relative
|
|
Packit |
fd8b60 |
widths of the types is not known (size_t may be the same width as
|
|
Packit |
fd8b60 |
int or larger).
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
#define SNPRINTF_OVERFLOW(result, size) \
|
|
Packit |
fd8b60 |
((unsigned int)(result) >= (size_t)(size))
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if defined(_WIN32) || !defined(HAVE_STRERROR_R) || defined(STRERROR_R_CHAR_P)
|
|
Packit |
fd8b60 |
#define strerror_r k5_strerror_r
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
extern int k5_strerror_r(int errnum, char *buf, size_t buflen);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef HAVE_MKSTEMP
|
|
Packit |
fd8b60 |
extern int krb5int_mkstemp(char *);
|
|
Packit |
fd8b60 |
#define mkstemp krb5int_mkstemp
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef HAVE_GETTIMEOFDAY
|
|
Packit |
fd8b60 |
extern int krb5int_gettimeofday(struct timeval *tp, void *ignore);
|
|
Packit |
fd8b60 |
#define gettimeofday krb5int_gettimeofday
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Attempt to zero memory in a way that compilers won't optimize out.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* This mechanism should work even for heap storage about to be freed,
|
|
Packit |
fd8b60 |
* or automatic storage right before we return from a function.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Then, even if we leak uninitialized memory someplace, or UNIX
|
|
Packit |
fd8b60 |
* "core" files get created with world-read access, some of the most
|
|
Packit |
fd8b60 |
* sensitive data in the process memory will already be safely wiped.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* We're not going so far -- yet -- as to try to protect key data that
|
|
Packit |
fd8b60 |
* may have been written into swap space....
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
#ifdef _WIN32
|
|
Packit |
fd8b60 |
# define zap(ptr, len) SecureZeroMemory(ptr, len)
|
|
Packit |
fd8b60 |
#elif defined(__STDC_LIB_EXT1__)
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Use memset_s() which cannot be optimized out. Avoid memset_s(NULL, 0, 0, 0)
|
|
Packit |
fd8b60 |
* which would cause a runtime constraint violation.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
static inline void zap(void *ptr, size_t len)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (len > 0)
|
|
Packit |
fd8b60 |
memset_s(ptr, len, 0, len);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#elif defined(HAVE_EXPLICIT_BZERO)
|
|
Packit |
fd8b60 |
# define zap(ptr, len) explicit_bzero(ptr, len)
|
|
Packit |
fd8b60 |
#elif defined(HAVE_EXPLICIT_MEMSET)
|
|
Packit |
fd8b60 |
# define zap(ptr, len) explicit_memset(ptr, 0, len)
|
|
Packit |
fd8b60 |
#elif defined(__GNUC__) || defined(__clang__)
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Use an asm statement which declares a memory clobber to force the memset to
|
|
Packit |
fd8b60 |
* be carried out. Avoid memset(NULL, 0, 0) which has undefined behavior.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
static inline void zap(void *ptr, size_t len)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (len > 0)
|
|
Packit |
fd8b60 |
memset(ptr, 0, len);
|
|
Packit |
fd8b60 |
__asm__ __volatile__("" : : "g" (ptr) : "memory");
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Use a function from libkrb5support to defeat inlining unless link-time
|
|
Packit |
fd8b60 |
* optimization is used. The function uses a volatile pointer, which prevents
|
|
Packit |
fd8b60 |
* current compilers from optimizing out the memset.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
# define zap(ptr, len) krb5int_zap(ptr, len)
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
extern void krb5int_zap(void *ptr, size_t len);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Return 0 if the n-byte memory regions p1 and p2 are equal, and nonzero if
|
|
Packit |
fd8b60 |
* they are not. The function is intended to take the same amount of time
|
|
Packit |
fd8b60 |
* regardless of how many bytes of p1 and p2 are equal.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
int k5_bcmp(const void *p1, const void *p2, size_t n);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Split a path into parent directory and basename. Either output parameter
|
|
Packit |
fd8b60 |
* may be NULL if the caller doesn't need it. parent_out will be empty if path
|
|
Packit |
fd8b60 |
* has no basename. basename_out will be empty if path ends with a path
|
|
Packit |
fd8b60 |
* separator. Returns 0 on success or ENOMEM on allocation failure.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
long k5_path_split(const char *path, char **parent_out, char **basename_out);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Compose two path components, inserting the platform-appropriate path
|
|
Packit |
fd8b60 |
* separator if needed. If path2 is an absolute path, path1 will be discarded
|
|
Packit |
fd8b60 |
* and path_out will be a copy of path2. Returns 0 on success or ENOMEM on
|
|
Packit |
fd8b60 |
* allocation failure.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
long k5_path_join(const char *path1, const char *path2, char **path_out);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Return 1 if path is absolute, 0 if it is relative. */
|
|
Packit |
fd8b60 |
int k5_path_isabs(const char *path);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Localization macros. If we have gettext, define _ appropriately for
|
|
Packit |
fd8b60 |
* translating a string. If we do not have gettext, define _ and
|
|
Packit |
fd8b60 |
* bindtextdomain as no-ops. N_ is always a no-op; it marks a string for
|
|
Packit |
fd8b60 |
* extraction to pot files but does not translate it.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
#ifdef ENABLE_NLS
|
|
Packit |
fd8b60 |
#include <libintl.h>
|
|
Packit |
fd8b60 |
#define KRB5_TEXTDOMAIN "mit-krb5"
|
|
Packit |
fd8b60 |
#define _(s) dgettext(KRB5_TEXTDOMAIN, s)
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
#define _(s) s
|
|
Packit |
fd8b60 |
#define dgettext(d, m) m
|
|
Packit |
fd8b60 |
#define ngettext(m1, m2, n) (((n) == 1) ? m1 : m2)
|
|
Packit |
fd8b60 |
#define bindtextdomain(p, d)
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
#define N_(s) s
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if !defined(HAVE_GETOPT) || !defined(HAVE_UNISTD_H)
|
|
Packit |
fd8b60 |
/* Data objects imported from DLLs must be declared as such on Windows. */
|
|
Packit |
fd8b60 |
#if defined(_WIN32) && !defined(K5_GETOPT_C)
|
|
Packit |
fd8b60 |
#define K5_GETOPT_DECL __declspec(dllimport)
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
#define K5_GETOPT_DECL
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
K5_GETOPT_DECL extern int k5_opterr;
|
|
Packit |
fd8b60 |
K5_GETOPT_DECL extern int k5_optind;
|
|
Packit |
fd8b60 |
K5_GETOPT_DECL extern int k5_optopt;
|
|
Packit |
fd8b60 |
K5_GETOPT_DECL extern char *k5_optarg;
|
|
Packit |
fd8b60 |
#define opterr k5_opterr
|
|
Packit |
fd8b60 |
#define optind k5_optind
|
|
Packit |
fd8b60 |
#define optopt k5_optopt
|
|
Packit |
fd8b60 |
#define optarg k5_optarg
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
extern int k5_getopt(int nargc, char * const nargv[], const char *ostr);
|
|
Packit |
fd8b60 |
#define getopt k5_getopt
|
|
Packit |
fd8b60 |
#endif /* HAVE_GETOPT */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifdef HAVE_GETOPT_LONG
|
|
Packit |
fd8b60 |
#include <getopt.h>
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct option
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const char *name;
|
|
Packit |
fd8b60 |
int has_arg;
|
|
Packit |
fd8b60 |
int *flag;
|
|
Packit |
fd8b60 |
int val;
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define no_argument 0
|
|
Packit |
fd8b60 |
#define required_argument 1
|
|
Packit |
fd8b60 |
#define optional_argument 2
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
extern int k5_getopt_long(int nargc, char **nargv, char *options,
|
|
Packit |
fd8b60 |
struct option *long_options, int *index);
|
|
Packit |
fd8b60 |
#define getopt_long k5_getopt_long
|
|
Packit |
fd8b60 |
#endif /* HAVE_GETOPT_LONG */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if defined(_WIN32)
|
|
Packit |
fd8b60 |
/* On Windows there is never a need to ignore the process environment. */
|
|
Packit |
fd8b60 |
#define secure_getenv getenv
|
|
Packit |
fd8b60 |
#elif !defined(HAVE_SECURE_GETENV)
|
|
Packit |
fd8b60 |
#define secure_getenv k5_secure_getenv
|
|
Packit |
fd8b60 |
extern char *k5_secure_getenv(const char *name);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Set *fnames_out to a null-terminated list of filenames within dirname,
|
|
Packit |
fd8b60 |
* sorted according to strcmp(). Return 0 on success, or ENOENT/ENOMEM. */
|
|
Packit |
fd8b60 |
int k5_dir_filenames(const char *dirname, char ***fnames_out);
|
|
Packit |
fd8b60 |
void k5_free_filenames(char **fnames);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#endif /* K5_PLATFORM_H */
|