xref: /freebsd/crypto/krb5/src/include/k5-platform.h (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* include/k5-platform.h */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 2003, 2004, 2005, 2007, 2008, 2009 Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert /*
28*7f2fe78bSCy Schubert  * Some platform-dependent definitions to sync up the C support level.
29*7f2fe78bSCy Schubert  * Some to a C99-ish level, some related utility code.
30*7f2fe78bSCy Schubert  *
31*7f2fe78bSCy Schubert  * Currently:
32*7f2fe78bSCy Schubert  * + [u]int{8,16,32}_t types
33*7f2fe78bSCy Schubert  * + 64-bit types and load/store code
34*7f2fe78bSCy Schubert  * + SIZE_MAX
35*7f2fe78bSCy Schubert  * + shared library init/fini hooks
36*7f2fe78bSCy Schubert  * + consistent getpwnam/getpwuid interfaces
37*7f2fe78bSCy Schubert  * + va_copy fudged if not provided
38*7f2fe78bSCy Schubert  * + strlcpy/strlcat
39*7f2fe78bSCy Schubert  * + fnmatch
40*7f2fe78bSCy Schubert  * + [v]asprintf
41*7f2fe78bSCy Schubert  * + strerror_r
42*7f2fe78bSCy Schubert  * + mkstemp
43*7f2fe78bSCy Schubert  * + zap (support function and macro)
44*7f2fe78bSCy Schubert  * + constant time memory comparison
45*7f2fe78bSCy Schubert  * + path manipulation
46*7f2fe78bSCy Schubert  * + _, N_, dgettext, bindtextdomain (for localization)
47*7f2fe78bSCy Schubert  * + getopt_long
48*7f2fe78bSCy Schubert  * + secure_getenv
49*7f2fe78bSCy Schubert  * + fetching filenames from a directory
50*7f2fe78bSCy Schubert  */
51*7f2fe78bSCy Schubert 
52*7f2fe78bSCy Schubert #ifndef K5_PLATFORM_H
53*7f2fe78bSCy Schubert #define K5_PLATFORM_H
54*7f2fe78bSCy Schubert 
55*7f2fe78bSCy Schubert #include "autoconf.h"
56*7f2fe78bSCy Schubert #include <assert.h>
57*7f2fe78bSCy Schubert #include <string.h>
58*7f2fe78bSCy Schubert #include <stdarg.h>
59*7f2fe78bSCy Schubert #include <stdint.h>
60*7f2fe78bSCy Schubert #include <limits.h>
61*7f2fe78bSCy Schubert #include <stdlib.h>
62*7f2fe78bSCy Schubert #include <stdio.h>
63*7f2fe78bSCy Schubert #include <fcntl.h>
64*7f2fe78bSCy Schubert #include <errno.h>
65*7f2fe78bSCy Schubert #ifdef HAVE_FNMATCH_H
66*7f2fe78bSCy Schubert #include <fnmatch.h>
67*7f2fe78bSCy Schubert #endif
68*7f2fe78bSCy Schubert 
69*7f2fe78bSCy Schubert #ifdef HAVE_UNISTD_H
70*7f2fe78bSCy Schubert #include <unistd.h>
71*7f2fe78bSCy Schubert #endif
72*7f2fe78bSCy Schubert 
73*7f2fe78bSCy Schubert #ifdef _WIN32
74*7f2fe78bSCy Schubert #define CAN_COPY_VA_LIST
75*7f2fe78bSCy Schubert #endif
76*7f2fe78bSCy Schubert 
77*7f2fe78bSCy Schubert /* This attribute prevents unused function warnings in gcc and clang. */
78*7f2fe78bSCy Schubert #ifdef __GNUC__
79*7f2fe78bSCy Schubert #define UNUSED __attribute__((__unused__))
80*7f2fe78bSCy Schubert #else
81*7f2fe78bSCy Schubert #define UNUSED
82*7f2fe78bSCy Schubert #endif
83*7f2fe78bSCy Schubert 
84*7f2fe78bSCy Schubert #if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
85*7f2fe78bSCy Schubert #include <TargetConditionals.h>
86*7f2fe78bSCy Schubert #endif
87*7f2fe78bSCy Schubert 
88*7f2fe78bSCy Schubert /* Initialization and finalization function support for libraries.
89*7f2fe78bSCy Schubert 
90*7f2fe78bSCy Schubert    At top level, before the functions are defined or even declared:
91*7f2fe78bSCy Schubert    MAKE_INIT_FUNCTION(init_fn);
92*7f2fe78bSCy Schubert    MAKE_FINI_FUNCTION(fini_fn);
93*7f2fe78bSCy Schubert    Then:
94*7f2fe78bSCy Schubert    int init_fn(void) { ... }
95*7f2fe78bSCy Schubert    void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... }
96*7f2fe78bSCy Schubert    In code, in the same file:
97*7f2fe78bSCy Schubert    err = CALL_INIT_FUNCTION(init_fn);
98*7f2fe78bSCy Schubert 
99*7f2fe78bSCy Schubert    To trigger or verify the initializer invocation from another file,
100*7f2fe78bSCy Schubert    a helper function must be created.
101*7f2fe78bSCy Schubert 
102*7f2fe78bSCy Schubert    This model handles both the load-time execution (Windows) and
103*7f2fe78bSCy Schubert    delayed execution (pthread_once) approaches, and should be able to
104*7f2fe78bSCy Schubert    guarantee in both cases that the init function is run once, in one
105*7f2fe78bSCy Schubert    thread, before other stuff in the library is done; furthermore, the
106*7f2fe78bSCy Schubert    finalization code should only run if the initialization code did.
107*7f2fe78bSCy Schubert    (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via
108*7f2fe78bSCy Schubert    another function hidden in macros, but this is hairy enough
109*7f2fe78bSCy Schubert    already.)
110*7f2fe78bSCy Schubert 
111*7f2fe78bSCy Schubert    The init_fn and fini_fn names should be chosen such that any
112*7f2fe78bSCy Schubert    exported names staring with those names, and optionally followed by
113*7f2fe78bSCy Schubert    additional characters, fits in with any namespace constraints on
114*7f2fe78bSCy Schubert    the library in question.
115*7f2fe78bSCy Schubert 
116*7f2fe78bSCy Schubert 
117*7f2fe78bSCy Schubert    There's also PROGRAM_EXITING() currently always defined as zero.
118*7f2fe78bSCy Schubert    If there's some trivial way to find out if the fini function is
119*7f2fe78bSCy Schubert    being called because the program that the library is linked into is
120*7f2fe78bSCy Schubert    exiting, we can just skip all the work because the resources are
121*7f2fe78bSCy Schubert    about to be freed up anyways.  Generally this is likely to be the
122*7f2fe78bSCy Schubert    same as distinguishing whether the library was loaded dynamically
123*7f2fe78bSCy Schubert    while the program was running, or loaded as part of program
124*7f2fe78bSCy Schubert    startup.  On most platforms, I don't think we can distinguish these
125*7f2fe78bSCy Schubert    cases easily, and it's probably not worth expending any significant
126*7f2fe78bSCy Schubert    effort.  (Note in particular that atexit() won't do, because if the
127*7f2fe78bSCy Schubert    library is explicitly loaded and unloaded, it would have to be able
128*7f2fe78bSCy Schubert    to deregister the atexit callback function.  Also, the system limit
129*7f2fe78bSCy Schubert    on atexit callbacks may be small.)
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert 
132*7f2fe78bSCy Schubert    Implementation outline:
133*7f2fe78bSCy Schubert 
134*7f2fe78bSCy Schubert    Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that
135*7f2fe78bSCy Schubert    is sought at library build time, and code is added to invoke the
136*7f2fe78bSCy Schubert    function when the library is unloaded.  MAKE_INIT_FUNCTION does
137*7f2fe78bSCy Schubert    likewise, but the function is invoked when the library is loaded,
138*7f2fe78bSCy Schubert    and an extra variable is declared to hold an error code and a "yes
139*7f2fe78bSCy Schubert    the initializer ran" flag.  CALL_INIT_FUNCTION blows up if the flag
140*7f2fe78bSCy Schubert    isn't set, otherwise returns the error code.
141*7f2fe78bSCy Schubert 
142*7f2fe78bSCy Schubert    UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a
143*7f2fe78bSCy Schubert    name derived from the function name, containing a k5_once_t
144*7f2fe78bSCy Schubert    (pthread_once_t or int), an error code, and a pointer to the
145*7f2fe78bSCy Schubert    function.  The function itself is declared static, but the
146*7f2fe78bSCy Schubert    associated variable has external linkage.  CALL_INIT_FUNCTION
147*7f2fe78bSCy Schubert    ensures thath the function is called exactly once (pthread_once or
148*7f2fe78bSCy Schubert    just check the flag) and returns the stored error code (or the
149*7f2fe78bSCy Schubert    pthread_once error).
150*7f2fe78bSCy Schubert 
151*7f2fe78bSCy Schubert    (That's the basic idea.  With some debugging assert() calls and
152*7f2fe78bSCy Schubert    such, it's a bit more complicated.  And we also need to handle
153*7f2fe78bSCy Schubert    doing the pthread test at run time on systems where that works, so
154*7f2fe78bSCy Schubert    we use the k5_once_t stuff instead.)
155*7f2fe78bSCy Schubert 
156*7f2fe78bSCy Schubert    UNIX, with compiler support: MAKE_FINI_FUNCTION declares the
157*7f2fe78bSCy Schubert    function as a destructor, and the run time linker support or
158*7f2fe78bSCy Schubert    whatever will cause it to be invoked when the library is unloaded,
159*7f2fe78bSCy Schubert    the program ends, etc.
160*7f2fe78bSCy Schubert 
161*7f2fe78bSCy Schubert    UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with
162*7f2fe78bSCy Schubert    a magic name that is sought at library build time, and linker
163*7f2fe78bSCy Schubert    options are used to mark it as a finalization function for the
164*7f2fe78bSCy Schubert    library.  The symbol must be exported.
165*7f2fe78bSCy Schubert 
166*7f2fe78bSCy Schubert    UNIX, no library finalization support: The finalization function
167*7f2fe78bSCy Schubert    never runs, and we leak memory.  Tough.
168*7f2fe78bSCy Schubert 
169*7f2fe78bSCy Schubert    DELAY_INITIALIZER will be defined by the configure script if we
170*7f2fe78bSCy Schubert    want to use k5_once instead of load-time initialization.  That'll
171*7f2fe78bSCy Schubert    be the preferred method on most systems except Windows, where we
172*7f2fe78bSCy Schubert    have to initialize some mutexes.
173*7f2fe78bSCy Schubert 
174*7f2fe78bSCy Schubert 
175*7f2fe78bSCy Schubert 
176*7f2fe78bSCy Schubert 
177*7f2fe78bSCy Schubert    For maximum flexibility in defining the macros, the function name
178*7f2fe78bSCy Schubert    parameter should be a simple name, not even a macro defined as
179*7f2fe78bSCy Schubert    another name.  The function should have a unique name, and should
180*7f2fe78bSCy Schubert    conform to whatever namespace is used by the library in question.
181*7f2fe78bSCy Schubert    (We do have export lists, but (1) they're not used for all
182*7f2fe78bSCy Schubert    platforms, and (2) they're not used for static libraries.)
183*7f2fe78bSCy Schubert 
184*7f2fe78bSCy Schubert    If the macro expansion needs the function to have been declared, it
185*7f2fe78bSCy Schubert    must include a declaration.  If it is not necessary for the symbol
186*7f2fe78bSCy Schubert    name to be exported from the object file, the macro should declare
187*7f2fe78bSCy Schubert    it as "static".  Hence the signature must exactly match "void
188*7f2fe78bSCy Schubert    foo(void)".  (ANSI C allows a static declaration followed by a
189*7f2fe78bSCy Schubert    non-static one; the result is internal linkage.)  The macro
190*7f2fe78bSCy Schubert    expansion has to come before the function, because gcc apparently
191*7f2fe78bSCy Schubert    won't act on "__attribute__((constructor))" if it comes after the
192*7f2fe78bSCy Schubert    function definition.
193*7f2fe78bSCy Schubert 
194*7f2fe78bSCy Schubert    This is going to be compiler- and environment-specific, and may
195*7f2fe78bSCy Schubert    require some support at library build time, and/or "asm"
196*7f2fe78bSCy Schubert    statements.  But through macro expansion and auxiliary functions,
197*7f2fe78bSCy Schubert    we should be able to handle most things except #pragma.
198*7f2fe78bSCy Schubert 
199*7f2fe78bSCy Schubert    It's okay for this code to require that the library be built
200*7f2fe78bSCy Schubert    with the same compiler and compiler options throughout, but
201*7f2fe78bSCy Schubert    we shouldn't require that the library and application use the
202*7f2fe78bSCy Schubert    same compiler.
203*7f2fe78bSCy Schubert 
204*7f2fe78bSCy Schubert    For static libraries, we don't really care about cleanup too much,
205*7f2fe78bSCy Schubert    since it's all memory handling and mutex allocation which will all
206*7f2fe78bSCy Schubert    be cleaned up when the program exits.  Thus, it's okay if gcc-built
207*7f2fe78bSCy Schubert    static libraries don't play nicely with cc-built executables when
208*7f2fe78bSCy Schubert    it comes to static constructors, just as long as it doesn't cause
209*7f2fe78bSCy Schubert    linking to fail.
210*7f2fe78bSCy Schubert 
211*7f2fe78bSCy Schubert    For dynamic libraries on UNIX, we'll use pthread_once-type support
212*7f2fe78bSCy Schubert    to do delayed initialization, so if finalization can't be made to
213*7f2fe78bSCy Schubert    work, we'll only have memory leaks in a load/use/unload cycle.  If
214*7f2fe78bSCy Schubert    anyone (like, say, the OS vendor) complains about this, they can
215*7f2fe78bSCy Schubert    tell us how to get a shared library finalization function invoked
216*7f2fe78bSCy Schubert    automatically.
217*7f2fe78bSCy Schubert 
218*7f2fe78bSCy Schubert    Currently there's --disable-delayed-initialization for preventing
219*7f2fe78bSCy Schubert    the initialization from being delayed on UNIX, but that's mainly
220*7f2fe78bSCy Schubert    just for testing the linker options for initialization, and will
221*7f2fe78bSCy Schubert    probably be removed at some point.  */
222*7f2fe78bSCy Schubert 
223*7f2fe78bSCy Schubert /* Helper macros.  */
224*7f2fe78bSCy Schubert 
225*7f2fe78bSCy Schubert # define JOIN__2_2(A,B) A ## _ ## _ ## B
226*7f2fe78bSCy Schubert # define JOIN__2(A,B) JOIN__2_2(A,B)
227*7f2fe78bSCy Schubert 
228*7f2fe78bSCy Schubert /* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set,
229*7f2fe78bSCy Schubert    always provide a function by the expected name, even if we're
230*7f2fe78bSCy Schubert    delaying initialization.  */
231*7f2fe78bSCy Schubert 
232*7f2fe78bSCy Schubert #if defined(DELAY_INITIALIZER)
233*7f2fe78bSCy Schubert 
234*7f2fe78bSCy Schubert /* Run the initialization code during program execution, at the latest
235*7f2fe78bSCy Schubert    possible moment.  This means multiple threads may be active.  */
236*7f2fe78bSCy Schubert # include "k5-thread.h"
237*7f2fe78bSCy Schubert typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t;
238*7f2fe78bSCy Schubert # ifdef USE_LINKER_INIT_OPTION
239*7f2fe78bSCy Schubert #  define MAYBE_DUMMY_INIT(NAME)                \
240*7f2fe78bSCy Schubert         void JOIN__2(NAME, auxinit) () { }
241*7f2fe78bSCy Schubert # else
242*7f2fe78bSCy Schubert #  define MAYBE_DUMMY_INIT(NAME)
243*7f2fe78bSCy Schubert # endif
244*7f2fe78bSCy Schubert # ifdef __GNUC__
245*7f2fe78bSCy Schubert /* Do it in macro form so we get the file/line of the invocation if
246*7f2fe78bSCy Schubert    the assertion fails.  */
247*7f2fe78bSCy Schubert #  define k5_call_init_function(I)                                      \
248*7f2fe78bSCy Schubert         (__extension__ ({                                               \
249*7f2fe78bSCy Schubert                 k5_init_t *k5int_i = (I);                               \
250*7f2fe78bSCy Schubert                 int k5int_err = k5_once(&k5int_i->once, k5int_i->fn);   \
251*7f2fe78bSCy Schubert                 (k5int_err                                              \
252*7f2fe78bSCy Schubert                  ? k5int_err                                            \
253*7f2fe78bSCy Schubert                  : (assert(k5int_i->did_run != 0), k5int_i->error));    \
254*7f2fe78bSCy Schubert             }))
255*7f2fe78bSCy Schubert #  define MAYBE_DEFINE_CALLINIT_FUNCTION
256*7f2fe78bSCy Schubert # else
257*7f2fe78bSCy Schubert #  define MAYBE_DEFINE_CALLINIT_FUNCTION                        \
258*7f2fe78bSCy Schubert         static inline int k5_call_init_function(k5_init_t *i)   \
259*7f2fe78bSCy Schubert         {                                                       \
260*7f2fe78bSCy Schubert             int err;                                            \
261*7f2fe78bSCy Schubert             err = k5_once(&i->once, i->fn);                     \
262*7f2fe78bSCy Schubert             if (err)                                            \
263*7f2fe78bSCy Schubert                 return err;                                     \
264*7f2fe78bSCy Schubert             assert (i->did_run != 0);                           \
265*7f2fe78bSCy Schubert             return i->error;                                    \
266*7f2fe78bSCy Schubert         }
267*7f2fe78bSCy Schubert # endif
268*7f2fe78bSCy Schubert # define MAKE_INIT_FUNCTION(NAME)                               \
269*7f2fe78bSCy Schubert         static int NAME(void);                                  \
270*7f2fe78bSCy Schubert         MAYBE_DUMMY_INIT(NAME)                                  \
271*7f2fe78bSCy Schubert         /* forward declaration for use in initializer */        \
272*7f2fe78bSCy Schubert         static void JOIN__2(NAME, aux) (void);                  \
273*7f2fe78bSCy Schubert         static k5_init_t JOIN__2(NAME, once) =                  \
274*7f2fe78bSCy Schubert                 { K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) };     \
275*7f2fe78bSCy Schubert         MAYBE_DEFINE_CALLINIT_FUNCTION                          \
276*7f2fe78bSCy Schubert         static void JOIN__2(NAME, aux) (void)                   \
277*7f2fe78bSCy Schubert         {                                                       \
278*7f2fe78bSCy Schubert             JOIN__2(NAME, once).did_run = 1;                    \
279*7f2fe78bSCy Schubert             JOIN__2(NAME, once).error = NAME();                 \
280*7f2fe78bSCy Schubert         }                                                       \
281*7f2fe78bSCy Schubert         /* so ';' following macro use won't get error */        \
282*7f2fe78bSCy Schubert         static int NAME(void)
283*7f2fe78bSCy Schubert # define CALL_INIT_FUNCTION(NAME)       \
284*7f2fe78bSCy Schubert         k5_call_init_function(& JOIN__2(NAME, once))
285*7f2fe78bSCy Schubert /* This should be called in finalization only, so we shouldn't have
286*7f2fe78bSCy Schubert    multiple active threads mucking around in our library at this
287*7f2fe78bSCy Schubert    point.  So ignore the once_t object and just look at the flag.
288*7f2fe78bSCy Schubert 
289*7f2fe78bSCy Schubert    XXX Could we have problems with memory coherence between processors
290*7f2fe78bSCy Schubert    if we don't invoke mutex/once routines?  Probably not, the
291*7f2fe78bSCy Schubert    application code should already be coordinating things such that
292*7f2fe78bSCy Schubert    the library code is not in use by this point, and memory
293*7f2fe78bSCy Schubert    synchronization will be needed there.  */
294*7f2fe78bSCy Schubert # define INITIALIZER_RAN(NAME)  \
295*7f2fe78bSCy Schubert         (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0)
296*7f2fe78bSCy Schubert 
297*7f2fe78bSCy Schubert # define PROGRAM_EXITING()              (0)
298*7f2fe78bSCy Schubert 
299*7f2fe78bSCy Schubert #elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS)
300*7f2fe78bSCy Schubert 
301*7f2fe78bSCy Schubert /* Run initializer at load time, via GCC/C++ hook magic.  */
302*7f2fe78bSCy Schubert 
303*7f2fe78bSCy Schubert # ifdef USE_LINKER_INIT_OPTION
304*7f2fe78bSCy Schubert      /* Both gcc and linker option??  Favor gcc.  */
305*7f2fe78bSCy Schubert #  define MAYBE_DUMMY_INIT(NAME)                \
306*7f2fe78bSCy Schubert         void JOIN__2(NAME, auxinit) () { }
307*7f2fe78bSCy Schubert # else
308*7f2fe78bSCy Schubert #  define MAYBE_DUMMY_INIT(NAME)
309*7f2fe78bSCy Schubert # endif
310*7f2fe78bSCy Schubert 
311*7f2fe78bSCy Schubert typedef struct { int error; unsigned char did_run; } k5_init_t;
312*7f2fe78bSCy Schubert # define MAKE_INIT_FUNCTION(NAME)               \
313*7f2fe78bSCy Schubert         MAYBE_DUMMY_INIT(NAME)                  \
314*7f2fe78bSCy Schubert         static k5_init_t JOIN__2(NAME, ran)     \
315*7f2fe78bSCy Schubert                 = { 0, 2 };                     \
316*7f2fe78bSCy Schubert         static void JOIN__2(NAME, aux)(void)    \
317*7f2fe78bSCy Schubert             __attribute__((constructor));       \
318*7f2fe78bSCy Schubert         static int NAME(void);                  \
319*7f2fe78bSCy Schubert         static void JOIN__2(NAME, aux)(void)    \
320*7f2fe78bSCy Schubert         {                                       \
321*7f2fe78bSCy Schubert             JOIN__2(NAME, ran).error = NAME();  \
322*7f2fe78bSCy Schubert             JOIN__2(NAME, ran).did_run = 3;     \
323*7f2fe78bSCy Schubert         }                                       \
324*7f2fe78bSCy Schubert         static int NAME(void)
325*7f2fe78bSCy Schubert # define CALL_INIT_FUNCTION(NAME)               \
326*7f2fe78bSCy Schubert         (JOIN__2(NAME, ran).did_run == 3        \
327*7f2fe78bSCy Schubert          ? JOIN__2(NAME, ran).error             \
328*7f2fe78bSCy Schubert          : (abort(),0))
329*7f2fe78bSCy Schubert # define INITIALIZER_RAN(NAME)  (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0)
330*7f2fe78bSCy Schubert 
331*7f2fe78bSCy Schubert # define PROGRAM_EXITING()              (0)
332*7f2fe78bSCy Schubert 
333*7f2fe78bSCy Schubert #elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32)
334*7f2fe78bSCy Schubert 
335*7f2fe78bSCy Schubert /* Run initializer at load time, via linker magic, or in the
336*7f2fe78bSCy Schubert    case of WIN32, win_glue.c hard-coded knowledge.  */
337*7f2fe78bSCy Schubert typedef struct { int error; unsigned char did_run; } k5_init_t;
338*7f2fe78bSCy Schubert # define MAKE_INIT_FUNCTION(NAME)               \
339*7f2fe78bSCy Schubert         static k5_init_t JOIN__2(NAME, ran)     \
340*7f2fe78bSCy Schubert                 = { 0, 2 };                     \
341*7f2fe78bSCy Schubert         static int NAME(void);                  \
342*7f2fe78bSCy Schubert         void JOIN__2(NAME, auxinit)()           \
343*7f2fe78bSCy Schubert         {                                       \
344*7f2fe78bSCy Schubert             JOIN__2(NAME, ran).error = NAME();  \
345*7f2fe78bSCy Schubert             JOIN__2(NAME, ran).did_run = 3;     \
346*7f2fe78bSCy Schubert         }                                       \
347*7f2fe78bSCy Schubert         static int NAME(void)
348*7f2fe78bSCy Schubert # define CALL_INIT_FUNCTION(NAME)               \
349*7f2fe78bSCy Schubert         (JOIN__2(NAME, ran).did_run == 3        \
350*7f2fe78bSCy Schubert          ? JOIN__2(NAME, ran).error             \
351*7f2fe78bSCy Schubert          : (abort(),0))
352*7f2fe78bSCy Schubert # define INITIALIZER_RAN(NAME)  \
353*7f2fe78bSCy Schubert         (JOIN__2(NAME, ran).error == 0)
354*7f2fe78bSCy Schubert 
355*7f2fe78bSCy Schubert # define PROGRAM_EXITING()              (0)
356*7f2fe78bSCy Schubert 
357*7f2fe78bSCy Schubert #else
358*7f2fe78bSCy Schubert 
359*7f2fe78bSCy Schubert # error "Don't know how to do load-time initializers for this configuration."
360*7f2fe78bSCy Schubert 
361*7f2fe78bSCy Schubert # define PROGRAM_EXITING()              (0)
362*7f2fe78bSCy Schubert 
363*7f2fe78bSCy Schubert #endif
364*7f2fe78bSCy Schubert 
365*7f2fe78bSCy Schubert 
366*7f2fe78bSCy Schubert 
367*7f2fe78bSCy Schubert #if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32)
368*7f2fe78bSCy Schubert /* If we're told the linker option will be used, it doesn't really
369*7f2fe78bSCy Schubert    matter what compiler we're using.  Do it the same way
370*7f2fe78bSCy Schubert    regardless.  */
371*7f2fe78bSCy Schubert 
372*7f2fe78bSCy Schubert # ifdef __hpux
373*7f2fe78bSCy Schubert 
374*7f2fe78bSCy Schubert      /* On HP-UX, we need this auxiliary function.  At dynamic load or
375*7f2fe78bSCy Schubert         unload time (but *not* program startup and termination for
376*7f2fe78bSCy Schubert         link-time specified libraries), the linker-indicated function
377*7f2fe78bSCy Schubert         is called with a handle on the library and a flag indicating
378*7f2fe78bSCy Schubert         whether it's being loaded or unloaded.
379*7f2fe78bSCy Schubert 
380*7f2fe78bSCy Schubert         The "real" fini function doesn't need to be exported, so
381*7f2fe78bSCy Schubert         declare it static.
382*7f2fe78bSCy Schubert 
383*7f2fe78bSCy Schubert         As usual, the final declaration is just for syntactic
384*7f2fe78bSCy Schubert         convenience, so the top-level invocation of this macro can be
385*7f2fe78bSCy Schubert         followed by a semicolon.  */
386*7f2fe78bSCy Schubert 
387*7f2fe78bSCy Schubert #  include <dl.h>
388*7f2fe78bSCy Schubert #  define MAKE_FINI_FUNCTION(NAME)                                          \
389*7f2fe78bSCy Schubert         static void NAME(void);                                             \
390*7f2fe78bSCy Schubert         void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \
391*7f2fe78bSCy Schubert         void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); }     \
392*7f2fe78bSCy Schubert         static void NAME(void)
393*7f2fe78bSCy Schubert 
394*7f2fe78bSCy Schubert # else /* not hpux */
395*7f2fe78bSCy Schubert 
396*7f2fe78bSCy Schubert #  define MAKE_FINI_FUNCTION(NAME)      \
397*7f2fe78bSCy Schubert         void NAME(void)
398*7f2fe78bSCy Schubert 
399*7f2fe78bSCy Schubert # endif
400*7f2fe78bSCy Schubert 
401*7f2fe78bSCy Schubert #elif !defined(SHARED)
402*7f2fe78bSCy Schubert 
403*7f2fe78bSCy Schubert /*
404*7f2fe78bSCy Schubert  * In this case, we just don't care about finalization.  The code will still
405*7f2fe78bSCy Schubert  * define the function, but we won't do anything with it.
406*7f2fe78bSCy Schubert  */
407*7f2fe78bSCy Schubert # define MAKE_FINI_FUNCTION(NAME)               \
408*7f2fe78bSCy Schubert         static void NAME(void) UNUSED
409*7f2fe78bSCy Schubert 
410*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS)
411*7f2fe78bSCy Schubert /* If we're using gcc, if the C++ support works, the compiler should
412*7f2fe78bSCy Schubert    build executables and shared libraries that support the use of
413*7f2fe78bSCy Schubert    static constructors and destructors.  The C compiler supports a
414*7f2fe78bSCy Schubert    function attribute that makes use of the same facility as C++.
415*7f2fe78bSCy Schubert 
416*7f2fe78bSCy Schubert    XXX How do we know if the C++ support actually works?  */
417*7f2fe78bSCy Schubert # define MAKE_FINI_FUNCTION(NAME)       \
418*7f2fe78bSCy Schubert         static void NAME(void) __attribute__((destructor))
419*7f2fe78bSCy Schubert 
420*7f2fe78bSCy Schubert #else
421*7f2fe78bSCy Schubert 
422*7f2fe78bSCy Schubert # error "Don't know how to do unload-time finalization for this configuration."
423*7f2fe78bSCy Schubert 
424*7f2fe78bSCy Schubert #endif
425*7f2fe78bSCy Schubert 
426*7f2fe78bSCy Schubert #ifndef SIZE_MAX
427*7f2fe78bSCy Schubert # define SIZE_MAX ((size_t)((size_t)0 - 1))
428*7f2fe78bSCy Schubert #endif
429*7f2fe78bSCy Schubert 
430*7f2fe78bSCy Schubert #ifdef _WIN32
431*7f2fe78bSCy Schubert # define SSIZE_MAX ((ssize_t)(SIZE_MAX/2))
432*7f2fe78bSCy Schubert #endif
433*7f2fe78bSCy Schubert 
434*7f2fe78bSCy Schubert /* Read and write integer values as (unaligned) octet strings in
435*7f2fe78bSCy Schubert    specific byte orders.  Add per-platform optimizations as
436*7f2fe78bSCy Schubert    needed.  */
437*7f2fe78bSCy Schubert 
438*7f2fe78bSCy Schubert #if HAVE_ENDIAN_H
439*7f2fe78bSCy Schubert # include <endian.h>
440*7f2fe78bSCy Schubert #elif HAVE_MACHINE_ENDIAN_H
441*7f2fe78bSCy Schubert # include <machine/endian.h>
442*7f2fe78bSCy Schubert #endif
443*7f2fe78bSCy Schubert /* Check for BIG/LITTLE_ENDIAN macros.  If exactly one is defined, use
444*7f2fe78bSCy Schubert    it.  If both are defined, then BYTE_ORDER should be defined and
445*7f2fe78bSCy Schubert    match one of them.  Try those symbols, then try again with an
446*7f2fe78bSCy Schubert    underscore prefix.  */
447*7f2fe78bSCy Schubert #if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
448*7f2fe78bSCy Schubert # if BYTE_ORDER == BIG_ENDIAN
449*7f2fe78bSCy Schubert #  define K5_BE
450*7f2fe78bSCy Schubert # endif
451*7f2fe78bSCy Schubert # if BYTE_ORDER == LITTLE_ENDIAN
452*7f2fe78bSCy Schubert #  define K5_LE
453*7f2fe78bSCy Schubert # endif
454*7f2fe78bSCy Schubert #elif defined(BIG_ENDIAN)
455*7f2fe78bSCy Schubert # define K5_BE
456*7f2fe78bSCy Schubert #elif defined(LITTLE_ENDIAN)
457*7f2fe78bSCy Schubert # define K5_LE
458*7f2fe78bSCy Schubert #elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
459*7f2fe78bSCy Schubert # if _BYTE_ORDER == _BIG_ENDIAN
460*7f2fe78bSCy Schubert #  define K5_BE
461*7f2fe78bSCy Schubert # endif
462*7f2fe78bSCy Schubert # if _BYTE_ORDER == _LITTLE_ENDIAN
463*7f2fe78bSCy Schubert #  define K5_LE
464*7f2fe78bSCy Schubert # endif
465*7f2fe78bSCy Schubert #elif defined(_BIG_ENDIAN)
466*7f2fe78bSCy Schubert # define K5_BE
467*7f2fe78bSCy Schubert #elif defined(_LITTLE_ENDIAN)
468*7f2fe78bSCy Schubert # define K5_LE
469*7f2fe78bSCy Schubert #elif defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
470*7f2fe78bSCy Schubert # define K5_BE
471*7f2fe78bSCy Schubert #elif defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
472*7f2fe78bSCy Schubert # define K5_LE
473*7f2fe78bSCy Schubert #endif
474*7f2fe78bSCy Schubert #if !defined(K5_BE) && !defined(K5_LE)
475*7f2fe78bSCy Schubert /* Look for some architectures we know about.
476*7f2fe78bSCy Schubert 
477*7f2fe78bSCy Schubert    MIPS can use either byte order, but the preprocessor tells us which
478*7f2fe78bSCy Schubert    mode we're compiling for.  The GCC config files indicate that
479*7f2fe78bSCy Schubert    variants of Alpha and IA64 might be out there with both byte
480*7f2fe78bSCy Schubert    orders, but until we encounter the "wrong" ones in the real world,
481*7f2fe78bSCy Schubert    just go with the default (unless there are cpp predefines to help
482*7f2fe78bSCy Schubert    us there too).
483*7f2fe78bSCy Schubert 
484*7f2fe78bSCy Schubert    As far as I know, only PDP11 and ARM (which we don't handle here)
485*7f2fe78bSCy Schubert    have strange byte orders where an 8-byte value isn't laid out as
486*7f2fe78bSCy Schubert    either 12345678 or 87654321.  */
487*7f2fe78bSCy Schubert # if defined(__i386__) || defined(_MIPSEL) || defined(__alpha__) || (defined(__ia64__) && !defined(__hpux))
488*7f2fe78bSCy Schubert #  define K5_LE
489*7f2fe78bSCy Schubert # endif
490*7f2fe78bSCy Schubert # if defined(__hppa__) || defined(__rs6000__) || defined(__sparc__) || defined(_MIPSEB) || defined(__m68k__) || defined(__sparc64__) || defined(__ppc__) || defined(__ppc64__) || (defined(__hpux) && defined(__ia64__))
491*7f2fe78bSCy Schubert #  define K5_BE
492*7f2fe78bSCy Schubert # endif
493*7f2fe78bSCy Schubert #endif
494*7f2fe78bSCy Schubert #if defined(K5_BE) && defined(K5_LE)
495*7f2fe78bSCy Schubert # error "oops, check the byte order macros"
496*7f2fe78bSCy Schubert #endif
497*7f2fe78bSCy Schubert 
498*7f2fe78bSCy Schubert /* Optimize for GCC on platforms with known byte orders.
499*7f2fe78bSCy Schubert 
500*7f2fe78bSCy Schubert    GCC's packed structures can be written to with any alignment; the
501*7f2fe78bSCy Schubert    compiler will use byte operations, unaligned-word operations, or
502*7f2fe78bSCy Schubert    normal memory ops as appropriate for the architecture.
503*7f2fe78bSCy Schubert 
504*7f2fe78bSCy Schubert    This assumes the availability of uint##_t types, which should work
505*7f2fe78bSCy Schubert    on most of our platforms except Windows, where we're not using
506*7f2fe78bSCy Schubert    GCC.  */
507*7f2fe78bSCy Schubert #ifdef __GNUC__
508*7f2fe78bSCy Schubert # define PUT(SIZE,PTR,VAL)      (((struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i = (VAL))
509*7f2fe78bSCy Schubert # define GET(SIZE,PTR)          (((const struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i)
510*7f2fe78bSCy Schubert # define PUTSWAPPED(SIZE,PTR,VAL)       PUT(SIZE,PTR,SWAP##SIZE(VAL))
511*7f2fe78bSCy Schubert # define GETSWAPPED(SIZE,PTR)           SWAP##SIZE(GET(SIZE,PTR))
512*7f2fe78bSCy Schubert #endif
513*7f2fe78bSCy Schubert /* To do: Define SWAP16, SWAP32, SWAP64 macros to byte-swap values
514*7f2fe78bSCy Schubert    with the indicated numbers of bits.
515*7f2fe78bSCy Schubert 
516*7f2fe78bSCy Schubert    Linux: byteswap.h, bswap_16 etc.
517*7f2fe78bSCy Schubert    Solaris 10: none
518*7f2fe78bSCy Schubert    macOS: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong}
519*7f2fe78bSCy Schubert    NetBSD: sys/bswap.h, bswap16 etc.  */
520*7f2fe78bSCy Schubert 
521*7f2fe78bSCy Schubert #if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16)
522*7f2fe78bSCy Schubert # include <byteswap.h>
523*7f2fe78bSCy Schubert # define SWAP16                 bswap_16
524*7f2fe78bSCy Schubert # define SWAP32                 bswap_32
525*7f2fe78bSCy Schubert # ifdef HAVE_BSWAP_64
526*7f2fe78bSCy Schubert #  define SWAP64                bswap_64
527*7f2fe78bSCy Schubert # endif
528*7f2fe78bSCy Schubert #elif TARGET_OS_MAC
529*7f2fe78bSCy Schubert # include <architecture/byte_order.h>
530*7f2fe78bSCy Schubert # define SWAP16                k5_swap16
k5_swap16(unsigned int x)531*7f2fe78bSCy Schubert static inline unsigned int k5_swap16 (unsigned int x) {
532*7f2fe78bSCy Schubert     x &= 0xffff;
533*7f2fe78bSCy Schubert     return (x >> 8) | ((x & 0xff) << 8);
534*7f2fe78bSCy Schubert }
535*7f2fe78bSCy Schubert # define SWAP32                 OSSwapInt32
536*7f2fe78bSCy Schubert # define SWAP64                 OSSwapInt64
537*7f2fe78bSCy Schubert #elif defined(HAVE_SYS_BSWAP_H)
538*7f2fe78bSCy Schubert /* XXX NetBSD/x86 5.0.1 defines bswap16 and bswap32 as inline
539*7f2fe78bSCy Schubert    functions only, so autoconf doesn't pick up on their existence.
540*7f2fe78bSCy Schubert    So, no feature macro test for them here.  The 64-bit version isn't
541*7f2fe78bSCy Schubert    inline at all, though, for whatever reason.  */
542*7f2fe78bSCy Schubert # include <sys/bswap.h>
543*7f2fe78bSCy Schubert # define SWAP16                 bswap16
544*7f2fe78bSCy Schubert # define SWAP32                 bswap32
545*7f2fe78bSCy Schubert /* However, bswap64 causes lots of warnings about 'long long'
546*7f2fe78bSCy Schubert    constants; probably only on 32-bit platforms.  */
547*7f2fe78bSCy Schubert # if LONG_MAX > 0x7fffffffL
548*7f2fe78bSCy Schubert #  define SWAP64                bswap64
549*7f2fe78bSCy Schubert # endif
550*7f2fe78bSCy Schubert #endif
551*7f2fe78bSCy Schubert 
552*7f2fe78bSCy Schubert /* Note that on Windows at least this file can be included from C++
553*7f2fe78bSCy Schubert    source, so casts *from* void* are required.  */
554*7f2fe78bSCy Schubert static inline void
store_16_be(unsigned int val,void * vp)555*7f2fe78bSCy Schubert store_16_be (unsigned int val, void *vp)
556*7f2fe78bSCy Schubert {
557*7f2fe78bSCy Schubert     unsigned char *p = (unsigned char *) vp;
558*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
559*7f2fe78bSCy Schubert     PUT(16,p,val);
560*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
561*7f2fe78bSCy Schubert     PUTSWAPPED(16,p,val);
562*7f2fe78bSCy Schubert #else
563*7f2fe78bSCy Schubert     p[0] = (val >>  8) & 0xff;
564*7f2fe78bSCy Schubert     p[1] = (val      ) & 0xff;
565*7f2fe78bSCy Schubert #endif
566*7f2fe78bSCy Schubert }
567*7f2fe78bSCy Schubert static inline void
store_32_be(unsigned int val,void * vp)568*7f2fe78bSCy Schubert store_32_be (unsigned int val, void *vp)
569*7f2fe78bSCy Schubert {
570*7f2fe78bSCy Schubert     unsigned char *p = (unsigned char *) vp;
571*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
572*7f2fe78bSCy Schubert     PUT(32,p,val);
573*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
574*7f2fe78bSCy Schubert     PUTSWAPPED(32,p,val);
575*7f2fe78bSCy Schubert #else
576*7f2fe78bSCy Schubert     p[0] = (val >> 24) & 0xff;
577*7f2fe78bSCy Schubert     p[1] = (val >> 16) & 0xff;
578*7f2fe78bSCy Schubert     p[2] = (val >>  8) & 0xff;
579*7f2fe78bSCy Schubert     p[3] = (val      ) & 0xff;
580*7f2fe78bSCy Schubert #endif
581*7f2fe78bSCy Schubert }
582*7f2fe78bSCy Schubert static inline void
store_64_be(uint64_t val,void * vp)583*7f2fe78bSCy Schubert store_64_be (uint64_t val, void *vp)
584*7f2fe78bSCy Schubert {
585*7f2fe78bSCy Schubert     unsigned char *p = (unsigned char *) vp;
586*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
587*7f2fe78bSCy Schubert     PUT(64,p,val);
588*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
589*7f2fe78bSCy Schubert     PUTSWAPPED(64,p,val);
590*7f2fe78bSCy Schubert #else
591*7f2fe78bSCy Schubert     p[0] = (unsigned char)((val >> 56) & 0xff);
592*7f2fe78bSCy Schubert     p[1] = (unsigned char)((val >> 48) & 0xff);
593*7f2fe78bSCy Schubert     p[2] = (unsigned char)((val >> 40) & 0xff);
594*7f2fe78bSCy Schubert     p[3] = (unsigned char)((val >> 32) & 0xff);
595*7f2fe78bSCy Schubert     p[4] = (unsigned char)((val >> 24) & 0xff);
596*7f2fe78bSCy Schubert     p[5] = (unsigned char)((val >> 16) & 0xff);
597*7f2fe78bSCy Schubert     p[6] = (unsigned char)((val >>  8) & 0xff);
598*7f2fe78bSCy Schubert     p[7] = (unsigned char)((val      ) & 0xff);
599*7f2fe78bSCy Schubert #endif
600*7f2fe78bSCy Schubert }
601*7f2fe78bSCy Schubert static inline unsigned short
load_16_be(const void * cvp)602*7f2fe78bSCy Schubert load_16_be (const void *cvp)
603*7f2fe78bSCy Schubert {
604*7f2fe78bSCy Schubert     const unsigned char *p = (const unsigned char *) cvp;
605*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
606*7f2fe78bSCy Schubert     return GET(16,p);
607*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
608*7f2fe78bSCy Schubert     return GETSWAPPED(16,p);
609*7f2fe78bSCy Schubert #else
610*7f2fe78bSCy Schubert     return (p[1] | (p[0] << 8));
611*7f2fe78bSCy Schubert #endif
612*7f2fe78bSCy Schubert }
613*7f2fe78bSCy Schubert static inline unsigned int
load_32_be(const void * cvp)614*7f2fe78bSCy Schubert load_32_be (const void *cvp)
615*7f2fe78bSCy Schubert {
616*7f2fe78bSCy Schubert     const unsigned char *p = (const unsigned char *) cvp;
617*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
618*7f2fe78bSCy Schubert     return GET(32,p);
619*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
620*7f2fe78bSCy Schubert     return GETSWAPPED(32,p);
621*7f2fe78bSCy Schubert #else
622*7f2fe78bSCy Schubert     return (p[3] | (p[2] << 8)
623*7f2fe78bSCy Schubert             | ((uint32_t) p[1] << 16)
624*7f2fe78bSCy Schubert             | ((uint32_t) p[0] << 24));
625*7f2fe78bSCy Schubert #endif
626*7f2fe78bSCy Schubert }
627*7f2fe78bSCy Schubert static inline uint64_t
load_64_be(const void * cvp)628*7f2fe78bSCy Schubert load_64_be (const void *cvp)
629*7f2fe78bSCy Schubert {
630*7f2fe78bSCy Schubert     const unsigned char *p = (const unsigned char *) cvp;
631*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
632*7f2fe78bSCy Schubert     return GET(64,p);
633*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
634*7f2fe78bSCy Schubert     return GETSWAPPED(64,p);
635*7f2fe78bSCy Schubert #else
636*7f2fe78bSCy Schubert     return ((uint64_t)load_32_be(p) << 32) | load_32_be(p+4);
637*7f2fe78bSCy Schubert #endif
638*7f2fe78bSCy Schubert }
639*7f2fe78bSCy Schubert static inline void
store_16_le(unsigned int val,void * vp)640*7f2fe78bSCy Schubert store_16_le (unsigned int val, void *vp)
641*7f2fe78bSCy Schubert {
642*7f2fe78bSCy Schubert     unsigned char *p = (unsigned char *) vp;
643*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
644*7f2fe78bSCy Schubert     PUT(16,p,val);
645*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
646*7f2fe78bSCy Schubert     PUTSWAPPED(16,p,val);
647*7f2fe78bSCy Schubert #else
648*7f2fe78bSCy Schubert     p[1] = (val >>  8) & 0xff;
649*7f2fe78bSCy Schubert     p[0] = (val      ) & 0xff;
650*7f2fe78bSCy Schubert #endif
651*7f2fe78bSCy Schubert }
652*7f2fe78bSCy Schubert static inline void
store_32_le(unsigned int val,void * vp)653*7f2fe78bSCy Schubert store_32_le (unsigned int val, void *vp)
654*7f2fe78bSCy Schubert {
655*7f2fe78bSCy Schubert     unsigned char *p = (unsigned char *) vp;
656*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
657*7f2fe78bSCy Schubert     PUT(32,p,val);
658*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
659*7f2fe78bSCy Schubert     PUTSWAPPED(32,p,val);
660*7f2fe78bSCy Schubert #else
661*7f2fe78bSCy Schubert     p[3] = (val >> 24) & 0xff;
662*7f2fe78bSCy Schubert     p[2] = (val >> 16) & 0xff;
663*7f2fe78bSCy Schubert     p[1] = (val >>  8) & 0xff;
664*7f2fe78bSCy Schubert     p[0] = (val      ) & 0xff;
665*7f2fe78bSCy Schubert #endif
666*7f2fe78bSCy Schubert }
667*7f2fe78bSCy Schubert static inline void
store_64_le(uint64_t val,void * vp)668*7f2fe78bSCy Schubert store_64_le (uint64_t val, void *vp)
669*7f2fe78bSCy Schubert {
670*7f2fe78bSCy Schubert     unsigned char *p = (unsigned char *) vp;
671*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
672*7f2fe78bSCy Schubert     PUT(64,p,val);
673*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
674*7f2fe78bSCy Schubert     PUTSWAPPED(64,p,val);
675*7f2fe78bSCy Schubert #else
676*7f2fe78bSCy Schubert     p[7] = (unsigned char)((val >> 56) & 0xff);
677*7f2fe78bSCy Schubert     p[6] = (unsigned char)((val >> 48) & 0xff);
678*7f2fe78bSCy Schubert     p[5] = (unsigned char)((val >> 40) & 0xff);
679*7f2fe78bSCy Schubert     p[4] = (unsigned char)((val >> 32) & 0xff);
680*7f2fe78bSCy Schubert     p[3] = (unsigned char)((val >> 24) & 0xff);
681*7f2fe78bSCy Schubert     p[2] = (unsigned char)((val >> 16) & 0xff);
682*7f2fe78bSCy Schubert     p[1] = (unsigned char)((val >>  8) & 0xff);
683*7f2fe78bSCy Schubert     p[0] = (unsigned char)((val      ) & 0xff);
684*7f2fe78bSCy Schubert #endif
685*7f2fe78bSCy Schubert }
686*7f2fe78bSCy Schubert static inline unsigned short
load_16_le(const void * cvp)687*7f2fe78bSCy Schubert load_16_le (const void *cvp)
688*7f2fe78bSCy Schubert {
689*7f2fe78bSCy Schubert     const unsigned char *p = (const unsigned char *) cvp;
690*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
691*7f2fe78bSCy Schubert     return GET(16,p);
692*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
693*7f2fe78bSCy Schubert     return GETSWAPPED(16,p);
694*7f2fe78bSCy Schubert #else
695*7f2fe78bSCy Schubert     return (p[0] | (p[1] << 8));
696*7f2fe78bSCy Schubert #endif
697*7f2fe78bSCy Schubert }
698*7f2fe78bSCy Schubert static inline unsigned int
load_32_le(const void * cvp)699*7f2fe78bSCy Schubert load_32_le (const void *cvp)
700*7f2fe78bSCy Schubert {
701*7f2fe78bSCy Schubert     const unsigned char *p = (const unsigned char *) cvp;
702*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
703*7f2fe78bSCy Schubert     return GET(32,p);
704*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
705*7f2fe78bSCy Schubert     return GETSWAPPED(32,p);
706*7f2fe78bSCy Schubert #else
707*7f2fe78bSCy Schubert     return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
708*7f2fe78bSCy Schubert #endif
709*7f2fe78bSCy Schubert }
710*7f2fe78bSCy Schubert static inline uint64_t
load_64_le(const void * cvp)711*7f2fe78bSCy Schubert load_64_le (const void *cvp)
712*7f2fe78bSCy Schubert {
713*7f2fe78bSCy Schubert     const unsigned char *p = (const unsigned char *) cvp;
714*7f2fe78bSCy Schubert #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
715*7f2fe78bSCy Schubert     return GET(64,p);
716*7f2fe78bSCy Schubert #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
717*7f2fe78bSCy Schubert     return GETSWAPPED(64,p);
718*7f2fe78bSCy Schubert #else
719*7f2fe78bSCy Schubert     return ((uint64_t)load_32_le(p+4) << 32) | load_32_le(p);
720*7f2fe78bSCy Schubert #endif
721*7f2fe78bSCy Schubert }
722*7f2fe78bSCy Schubert 
723*7f2fe78bSCy Schubert #define UINT16_TYPE uint16_t
724*7f2fe78bSCy Schubert #define UINT32_TYPE uint32_t
725*7f2fe78bSCy Schubert 
726*7f2fe78bSCy Schubert static inline void
store_16_n(unsigned int val,void * vp)727*7f2fe78bSCy Schubert store_16_n (unsigned int val, void *vp)
728*7f2fe78bSCy Schubert {
729*7f2fe78bSCy Schubert     UINT16_TYPE n = val;
730*7f2fe78bSCy Schubert     memcpy(vp, &n, 2);
731*7f2fe78bSCy Schubert }
732*7f2fe78bSCy Schubert static inline void
store_32_n(unsigned int val,void * vp)733*7f2fe78bSCy Schubert store_32_n (unsigned int val, void *vp)
734*7f2fe78bSCy Schubert {
735*7f2fe78bSCy Schubert     UINT32_TYPE n = val;
736*7f2fe78bSCy Schubert     memcpy(vp, &n, 4);
737*7f2fe78bSCy Schubert }
738*7f2fe78bSCy Schubert static inline void
store_64_n(uint64_t val,void * vp)739*7f2fe78bSCy Schubert store_64_n (uint64_t val, void *vp)
740*7f2fe78bSCy Schubert {
741*7f2fe78bSCy Schubert     uint64_t n = val;
742*7f2fe78bSCy Schubert     memcpy(vp, &n, 8);
743*7f2fe78bSCy Schubert }
744*7f2fe78bSCy Schubert static inline unsigned short
load_16_n(const void * p)745*7f2fe78bSCy Schubert load_16_n (const void *p)
746*7f2fe78bSCy Schubert {
747*7f2fe78bSCy Schubert     UINT16_TYPE n;
748*7f2fe78bSCy Schubert     memcpy(&n, p, 2);
749*7f2fe78bSCy Schubert     return n;
750*7f2fe78bSCy Schubert }
751*7f2fe78bSCy Schubert static inline unsigned int
load_32_n(const void * p)752*7f2fe78bSCy Schubert load_32_n (const void *p)
753*7f2fe78bSCy Schubert {
754*7f2fe78bSCy Schubert     UINT32_TYPE n;
755*7f2fe78bSCy Schubert     memcpy(&n, p, 4);
756*7f2fe78bSCy Schubert     return n;
757*7f2fe78bSCy Schubert }
758*7f2fe78bSCy Schubert static inline uint64_t
load_64_n(const void * p)759*7f2fe78bSCy Schubert load_64_n (const void *p)
760*7f2fe78bSCy Schubert {
761*7f2fe78bSCy Schubert     uint64_t n;
762*7f2fe78bSCy Schubert     memcpy(&n, p, 8);
763*7f2fe78bSCy Schubert     return n;
764*7f2fe78bSCy Schubert }
765*7f2fe78bSCy Schubert #undef UINT16_TYPE
766*7f2fe78bSCy Schubert #undef UINT32_TYPE
767*7f2fe78bSCy Schubert 
768*7f2fe78bSCy Schubert /* Assume for simplicity that these swaps are identical.  */
769*7f2fe78bSCy Schubert static inline uint64_t
k5_htonll(uint64_t val)770*7f2fe78bSCy Schubert k5_htonll (uint64_t val)
771*7f2fe78bSCy Schubert {
772*7f2fe78bSCy Schubert #ifdef K5_BE
773*7f2fe78bSCy Schubert     return val;
774*7f2fe78bSCy Schubert #elif defined K5_LE && defined SWAP64
775*7f2fe78bSCy Schubert     return SWAP64 (val);
776*7f2fe78bSCy Schubert #else
777*7f2fe78bSCy Schubert     return load_64_be ((unsigned char *)&val);
778*7f2fe78bSCy Schubert #endif
779*7f2fe78bSCy Schubert }
780*7f2fe78bSCy Schubert static inline uint64_t
k5_ntohll(uint64_t val)781*7f2fe78bSCy Schubert k5_ntohll (uint64_t val)
782*7f2fe78bSCy Schubert {
783*7f2fe78bSCy Schubert     return k5_htonll (val);
784*7f2fe78bSCy Schubert }
785*7f2fe78bSCy Schubert 
786*7f2fe78bSCy Schubert /* Make the interfaces to getpwnam and getpwuid consistent.
787*7f2fe78bSCy Schubert    Model the wrappers on the POSIX thread-safe versions, but
788*7f2fe78bSCy Schubert    use the unsafe system versions if the safe ones don't exist
789*7f2fe78bSCy Schubert    or we can't figure out their interfaces.  */
790*7f2fe78bSCy Schubert 
791*7f2fe78bSCy Schubert /* int k5_getpwnam_r(const char *, blah blah) */
792*7f2fe78bSCy Schubert #ifdef HAVE_GETPWNAM_R
793*7f2fe78bSCy Schubert # ifndef GETPWNAM_R_4_ARGS
794*7f2fe78bSCy Schubert /* POSIX */
795*7f2fe78bSCy Schubert #  define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT)   \
796*7f2fe78bSCy Schubert         (getpwnam_r(NAME,REC,BUF,BUFSIZE,OUT) == 0      \
797*7f2fe78bSCy Schubert          ? (*(OUT) == NULL ? -1 : 0) : -1)
798*7f2fe78bSCy Schubert # else
799*7f2fe78bSCy Schubert /* POSIX drafts? */
800*7f2fe78bSCy Schubert #  ifdef GETPWNAM_R_RETURNS_INT
801*7f2fe78bSCy Schubert #   define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT)  \
802*7f2fe78bSCy Schubert         (getpwnam_r(NAME,REC,BUF,BUFSIZE) == 0          \
803*7f2fe78bSCy Schubert          ? (*(OUT) = REC, 0)                            \
804*7f2fe78bSCy Schubert          : (*(OUT) = NULL, -1))
805*7f2fe78bSCy Schubert #  else
806*7f2fe78bSCy Schubert #   define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT)  \
807*7f2fe78bSCy Schubert         (*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
808*7f2fe78bSCy Schubert #  endif
809*7f2fe78bSCy Schubert # endif
810*7f2fe78bSCy Schubert #else /* no getpwnam_r, or can't figure out #args or return type */
811*7f2fe78bSCy Schubert /* Will get warnings about unused variables.  */
812*7f2fe78bSCy Schubert # define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
813*7f2fe78bSCy Schubert         (*(OUT) = getpwnam(NAME), *(OUT) == NULL ? -1 : 0)
814*7f2fe78bSCy Schubert #endif
815*7f2fe78bSCy Schubert 
816*7f2fe78bSCy Schubert /* int k5_getpwuid_r(uid_t, blah blah) */
817*7f2fe78bSCy Schubert #ifdef HAVE_GETPWUID_R
818*7f2fe78bSCy Schubert # ifndef GETPWUID_R_4_ARGS
819*7f2fe78bSCy Schubert /* POSIX */
820*7f2fe78bSCy Schubert #  define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT)    \
821*7f2fe78bSCy Schubert         (getpwuid_r(UID,REC,BUF,BUFSIZE,OUT) == 0       \
822*7f2fe78bSCy Schubert          ? (*(OUT) == NULL ? -1 : 0) : -1)
823*7f2fe78bSCy Schubert # else
824*7f2fe78bSCy Schubert /* POSIX drafts?  Yes, I mean to test GETPWNAM... here.  Less junk to
825*7f2fe78bSCy Schubert    do at configure time.  */
826*7f2fe78bSCy Schubert #  ifdef GETPWNAM_R_RETURNS_INT
827*7f2fe78bSCy Schubert #   define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT)   \
828*7f2fe78bSCy Schubert         (getpwuid_r(UID,REC,BUF,BUFSIZE) == 0           \
829*7f2fe78bSCy Schubert          ? (*(OUT) = REC, 0)                            \
830*7f2fe78bSCy Schubert          : (*(OUT) = NULL, -1))
831*7f2fe78bSCy Schubert #  else
832*7f2fe78bSCy Schubert #   define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT)  \
833*7f2fe78bSCy Schubert         (*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
834*7f2fe78bSCy Schubert #  endif
835*7f2fe78bSCy Schubert # endif
836*7f2fe78bSCy Schubert #else /* no getpwuid_r, or can't figure out #args or return type */
837*7f2fe78bSCy Schubert /* Will get warnings about unused variables.  */
838*7f2fe78bSCy Schubert # define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
839*7f2fe78bSCy Schubert         (*(OUT) = getpwuid(UID), *(OUT) == NULL ? -1 : 0)
840*7f2fe78bSCy Schubert #endif
841*7f2fe78bSCy Schubert 
842*7f2fe78bSCy Schubert /* Ensure, if possible, that the indicated file descriptor won't be
843*7f2fe78bSCy Schubert    kept open if we exec another process (e.g., launching a ccapi
844*7f2fe78bSCy Schubert    server).  If we don't know how to do it... well, just go about our
845*7f2fe78bSCy Schubert    business.  Probably most callers won't check the return status
846*7f2fe78bSCy Schubert    anyways.  */
847*7f2fe78bSCy Schubert 
848*7f2fe78bSCy Schubert /* Macros make the Sun compiler happier, and all variants of this do a
849*7f2fe78bSCy Schubert    single evaluation of the argument, and fcntl and fileno should
850*7f2fe78bSCy Schubert    produce reasonable error messages on type mismatches, on any system
851*7f2fe78bSCy Schubert    with F_SETFD.  */
852*7f2fe78bSCy Schubert #ifdef F_SETFD
853*7f2fe78bSCy Schubert # ifdef FD_CLOEXEC
854*7f2fe78bSCy Schubert #  define set_cloexec_fd(FD)    ((void)fcntl((FD), F_SETFD, FD_CLOEXEC))
855*7f2fe78bSCy Schubert # else
856*7f2fe78bSCy Schubert #  define set_cloexec_fd(FD)    ((void)fcntl((FD), F_SETFD, 1))
857*7f2fe78bSCy Schubert # endif
858*7f2fe78bSCy Schubert #else
859*7f2fe78bSCy Schubert # define set_cloexec_fd(FD)     ((void)(FD))
860*7f2fe78bSCy Schubert #endif
861*7f2fe78bSCy Schubert #define set_cloexec_file(F)     set_cloexec_fd(fileno(F))
862*7f2fe78bSCy Schubert 
863*7f2fe78bSCy Schubert /* Since the original ANSI C spec left it undefined whether or
864*7f2fe78bSCy Schubert    how you could copy around a va_list, C 99 added va_copy.
865*7f2fe78bSCy Schubert    For old implementations, let's do our best to fake it.
866*7f2fe78bSCy Schubert 
867*7f2fe78bSCy Schubert    XXX Doesn't yet handle implementations with __va_copy (early draft)
868*7f2fe78bSCy Schubert    or GCC's __builtin_va_copy.  */
869*7f2fe78bSCy Schubert #if defined(HAS_VA_COPY) || defined(va_copy)
870*7f2fe78bSCy Schubert /* Do nothing.  */
871*7f2fe78bSCy Schubert #elif defined(CAN_COPY_VA_LIST)
872*7f2fe78bSCy Schubert #define va_copy(dest, src)      ((dest) = (src))
873*7f2fe78bSCy Schubert #else
874*7f2fe78bSCy Schubert /* Assume array type, but still simply copyable.
875*7f2fe78bSCy Schubert 
876*7f2fe78bSCy Schubert    There is, theoretically, the possibility that va_start will
877*7f2fe78bSCy Schubert    allocate some storage pointed to by the va_list, and in that case
878*7f2fe78bSCy Schubert    we'll just lose.  If anyone cares, we could try to devise a test
879*7f2fe78bSCy Schubert    for that case.  */
880*7f2fe78bSCy Schubert #define va_copy(dest, src)      memcpy(dest, src, sizeof(va_list))
881*7f2fe78bSCy Schubert #endif
882*7f2fe78bSCy Schubert 
883*7f2fe78bSCy Schubert /* Provide strlcpy/strlcat interfaces. */
884*7f2fe78bSCy Schubert #ifndef HAVE_STRLCPY
885*7f2fe78bSCy Schubert #define strlcpy krb5int_strlcpy
886*7f2fe78bSCy Schubert #define strlcat krb5int_strlcat
887*7f2fe78bSCy Schubert extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz);
888*7f2fe78bSCy Schubert extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz);
889*7f2fe78bSCy Schubert #endif
890*7f2fe78bSCy Schubert 
891*7f2fe78bSCy Schubert /* Provide fnmatch interface. */
892*7f2fe78bSCy Schubert #ifndef HAVE_FNMATCH
893*7f2fe78bSCy Schubert #define fnmatch k5_fnmatch
894*7f2fe78bSCy Schubert int k5_fnmatch(const char *pattern, const char *string, int flags);
895*7f2fe78bSCy Schubert #define FNM_NOMATCH     1       /* Match failed. */
896*7f2fe78bSCy Schubert #define FNM_NOSYS       2       /* Function not implemented. */
897*7f2fe78bSCy Schubert #define FNM_NORES       3       /* Out of resources */
898*7f2fe78bSCy Schubert #define FNM_NOESCAPE    0x01    /* Disable backslash escaping. */
899*7f2fe78bSCy Schubert #define FNM_PATHNAME    0x02    /* Slash must be matched by slash. */
900*7f2fe78bSCy Schubert #define FNM_PERIOD      0x04    /* Period must be matched by period. */
901*7f2fe78bSCy Schubert #define FNM_CASEFOLD    0x08    /* Pattern is matched case-insensitive */
902*7f2fe78bSCy Schubert #define FNM_LEADING_DIR 0x10    /* Ignore /<tail> after Imatch. */
903*7f2fe78bSCy Schubert #endif
904*7f2fe78bSCy Schubert 
905*7f2fe78bSCy Schubert /* Provide [v]asprintf interfaces.  */
906*7f2fe78bSCy Schubert #ifndef HAVE_VSNPRINTF
907*7f2fe78bSCy Schubert #ifdef _WIN32
908*7f2fe78bSCy Schubert static inline int
vsnprintf(char * str,size_t size,const char * format,va_list args)909*7f2fe78bSCy Schubert vsnprintf(char *str, size_t size, const char *format, va_list args)
910*7f2fe78bSCy Schubert {
911*7f2fe78bSCy Schubert     va_list args_copy;
912*7f2fe78bSCy Schubert     int length;
913*7f2fe78bSCy Schubert 
914*7f2fe78bSCy Schubert     va_copy(args_copy, args);
915*7f2fe78bSCy Schubert     length = _vscprintf(format, args_copy);
916*7f2fe78bSCy Schubert     va_end(args_copy);
917*7f2fe78bSCy Schubert     if (size > 0) {
918*7f2fe78bSCy Schubert         _vsnprintf(str, size, format, args);
919*7f2fe78bSCy Schubert         str[size - 1] = '\0';
920*7f2fe78bSCy Schubert     }
921*7f2fe78bSCy Schubert     return length;
922*7f2fe78bSCy Schubert }
923*7f2fe78bSCy Schubert static inline int
snprintf(char * str,size_t size,const char * format,...)924*7f2fe78bSCy Schubert snprintf(char *str, size_t size, const char *format, ...)
925*7f2fe78bSCy Schubert {
926*7f2fe78bSCy Schubert     va_list args;
927*7f2fe78bSCy Schubert     int n;
928*7f2fe78bSCy Schubert 
929*7f2fe78bSCy Schubert     va_start(args, format);
930*7f2fe78bSCy Schubert     n = vsnprintf(str, size, format, args);
931*7f2fe78bSCy Schubert     va_end(args);
932*7f2fe78bSCy Schubert     return n;
933*7f2fe78bSCy Schubert }
934*7f2fe78bSCy Schubert #else /* not win32 */
935*7f2fe78bSCy Schubert #error We need an implementation of vsnprintf.
936*7f2fe78bSCy Schubert #endif /* win32? */
937*7f2fe78bSCy Schubert #endif /* no vsnprintf */
938*7f2fe78bSCy Schubert 
939*7f2fe78bSCy Schubert #ifndef HAVE_VASPRINTF
940*7f2fe78bSCy Schubert 
941*7f2fe78bSCy Schubert extern int krb5int_vasprintf(char **, const char *, va_list)
942*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
943*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 2, 0)))
944*7f2fe78bSCy Schubert #endif
945*7f2fe78bSCy Schubert     ;
946*7f2fe78bSCy Schubert extern int krb5int_asprintf(char **, const char *, ...)
947*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
948*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 2, 3)))
949*7f2fe78bSCy Schubert #endif
950*7f2fe78bSCy Schubert     ;
951*7f2fe78bSCy Schubert 
952*7f2fe78bSCy Schubert #define vasprintf krb5int_vasprintf
953*7f2fe78bSCy Schubert /* Assume HAVE_ASPRINTF iff HAVE_VASPRINTF.  */
954*7f2fe78bSCy Schubert #define asprintf krb5int_asprintf
955*7f2fe78bSCy Schubert 
956*7f2fe78bSCy Schubert #elif defined(NEED_VASPRINTF_PROTO)
957*7f2fe78bSCy Schubert 
958*7f2fe78bSCy Schubert extern int vasprintf(char **, const char *, va_list)
959*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
960*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 2, 0)))
961*7f2fe78bSCy Schubert #endif
962*7f2fe78bSCy Schubert     ;
963*7f2fe78bSCy Schubert extern int asprintf(char **, const char *, ...)
964*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
965*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 2, 3)))
966*7f2fe78bSCy Schubert #endif
967*7f2fe78bSCy Schubert     ;
968*7f2fe78bSCy Schubert 
969*7f2fe78bSCy Schubert #endif /* have vasprintf and prototype? */
970*7f2fe78bSCy Schubert 
971*7f2fe78bSCy Schubert /* Return true if the snprintf return value RESULT reflects a buffer
972*7f2fe78bSCy Schubert    overflow for the buffer size SIZE.
973*7f2fe78bSCy Schubert 
974*7f2fe78bSCy Schubert    We cast the result to unsigned int for two reasons.  First, old
975*7f2fe78bSCy Schubert    implementations of snprintf (such as the one in Solaris 9 and
976*7f2fe78bSCy Schubert    prior) return -1 on a buffer overflow.  Casting the result to -1
977*7f2fe78bSCy Schubert    will convert that value to UINT_MAX, which should compare larger
978*7f2fe78bSCy Schubert    than any reasonable buffer size.  Second, comparing signed and
979*7f2fe78bSCy Schubert    unsigned integers will generate warnings with some compilers, and
980*7f2fe78bSCy Schubert    can have unpredictable results, particularly when the relative
981*7f2fe78bSCy Schubert    widths of the types is not known (size_t may be the same width as
982*7f2fe78bSCy Schubert    int or larger).
983*7f2fe78bSCy Schubert */
984*7f2fe78bSCy Schubert #define SNPRINTF_OVERFLOW(result, size) \
985*7f2fe78bSCy Schubert     ((unsigned int)(result) >= (size_t)(size))
986*7f2fe78bSCy Schubert 
987*7f2fe78bSCy Schubert #if defined(_WIN32) || !defined(HAVE_STRERROR_R) || defined(STRERROR_R_CHAR_P)
988*7f2fe78bSCy Schubert #define strerror_r k5_strerror_r
989*7f2fe78bSCy Schubert #endif
990*7f2fe78bSCy Schubert extern int k5_strerror_r(int errnum, char *buf, size_t buflen);
991*7f2fe78bSCy Schubert 
992*7f2fe78bSCy Schubert #ifndef HAVE_MKSTEMP
993*7f2fe78bSCy Schubert extern int krb5int_mkstemp(char *);
994*7f2fe78bSCy Schubert #define mkstemp krb5int_mkstemp
995*7f2fe78bSCy Schubert #endif
996*7f2fe78bSCy Schubert 
997*7f2fe78bSCy Schubert #ifndef HAVE_GETTIMEOFDAY
998*7f2fe78bSCy Schubert extern int krb5int_gettimeofday(struct timeval *tp, void *ignore);
999*7f2fe78bSCy Schubert #define gettimeofday krb5int_gettimeofday
1000*7f2fe78bSCy Schubert #endif
1001*7f2fe78bSCy Schubert 
1002*7f2fe78bSCy Schubert /*
1003*7f2fe78bSCy Schubert  * Attempt to zero memory in a way that compilers won't optimize out.
1004*7f2fe78bSCy Schubert  *
1005*7f2fe78bSCy Schubert  * This mechanism should work even for heap storage about to be freed,
1006*7f2fe78bSCy Schubert  * or automatic storage right before we return from a function.
1007*7f2fe78bSCy Schubert  *
1008*7f2fe78bSCy Schubert  * Then, even if we leak uninitialized memory someplace, or UNIX
1009*7f2fe78bSCy Schubert  * "core" files get created with world-read access, some of the most
1010*7f2fe78bSCy Schubert  * sensitive data in the process memory will already be safely wiped.
1011*7f2fe78bSCy Schubert  *
1012*7f2fe78bSCy Schubert  * We're not going so far -- yet -- as to try to protect key data that
1013*7f2fe78bSCy Schubert  * may have been written into swap space....
1014*7f2fe78bSCy Schubert  */
1015*7f2fe78bSCy Schubert #ifdef _WIN32
1016*7f2fe78bSCy Schubert # define zap(ptr, len) SecureZeroMemory(ptr, len)
1017*7f2fe78bSCy Schubert #elif defined(__STDC_LIB_EXT1__)
1018*7f2fe78bSCy Schubert /*
1019*7f2fe78bSCy Schubert  * Use memset_s() which cannot be optimized out.  Avoid memset_s(NULL, 0, 0, 0)
1020*7f2fe78bSCy Schubert  * which would cause a runtime constraint violation.
1021*7f2fe78bSCy Schubert  */
zap(void * ptr,size_t len)1022*7f2fe78bSCy Schubert static inline void zap(void *ptr, size_t len)
1023*7f2fe78bSCy Schubert {
1024*7f2fe78bSCy Schubert     if (len > 0)
1025*7f2fe78bSCy Schubert         memset_s(ptr, len, 0, len);
1026*7f2fe78bSCy Schubert }
1027*7f2fe78bSCy Schubert #elif defined(HAVE_EXPLICIT_BZERO)
1028*7f2fe78bSCy Schubert # define zap(ptr, len) explicit_bzero(ptr, len)
1029*7f2fe78bSCy Schubert #elif defined(HAVE_EXPLICIT_MEMSET)
1030*7f2fe78bSCy Schubert # define zap(ptr, len) explicit_memset(ptr, 0, len)
1031*7f2fe78bSCy Schubert #elif defined(__GNUC__) || defined(__clang__)
1032*7f2fe78bSCy Schubert /*
1033*7f2fe78bSCy Schubert  * Use an asm statement which declares a memory clobber to force the memset to
1034*7f2fe78bSCy Schubert  * be carried out.  Avoid memset(NULL, 0, 0) which has undefined behavior.
1035*7f2fe78bSCy Schubert  */
zap(void * ptr,size_t len)1036*7f2fe78bSCy Schubert static inline void zap(void *ptr, size_t len)
1037*7f2fe78bSCy Schubert {
1038*7f2fe78bSCy Schubert     if (len > 0)
1039*7f2fe78bSCy Schubert         memset(ptr, 0, len);
1040*7f2fe78bSCy Schubert     __asm__ __volatile__("" : : "g" (ptr) : "memory");
1041*7f2fe78bSCy Schubert }
1042*7f2fe78bSCy Schubert #else
1043*7f2fe78bSCy Schubert /*
1044*7f2fe78bSCy Schubert  * Use a function from libkrb5support to defeat inlining unless link-time
1045*7f2fe78bSCy Schubert  * optimization is used.  The function uses a volatile pointer, which prevents
1046*7f2fe78bSCy Schubert  * current compilers from optimizing out the memset.
1047*7f2fe78bSCy Schubert  */
1048*7f2fe78bSCy Schubert # define zap(ptr, len) krb5int_zap(ptr, len)
1049*7f2fe78bSCy Schubert #endif
1050*7f2fe78bSCy Schubert 
1051*7f2fe78bSCy Schubert extern void krb5int_zap(void *ptr, size_t len);
1052*7f2fe78bSCy Schubert 
1053*7f2fe78bSCy Schubert /*
1054*7f2fe78bSCy Schubert  * Return 0 if the n-byte memory regions p1 and p2 are equal, and nonzero if
1055*7f2fe78bSCy Schubert  * they are not.  The function is intended to take the same amount of time
1056*7f2fe78bSCy Schubert  * regardless of how many bytes of p1 and p2 are equal.
1057*7f2fe78bSCy Schubert  */
1058*7f2fe78bSCy Schubert int k5_bcmp(const void *p1, const void *p2, size_t n);
1059*7f2fe78bSCy Schubert 
1060*7f2fe78bSCy Schubert /*
1061*7f2fe78bSCy Schubert  * Split a path into parent directory and basename.  Either output parameter
1062*7f2fe78bSCy Schubert  * may be NULL if the caller doesn't need it.  parent_out will be empty if path
1063*7f2fe78bSCy Schubert  * has no basename.  basename_out will be empty if path ends with a path
1064*7f2fe78bSCy Schubert  * separator.  Returns 0 on success or ENOMEM on allocation failure.
1065*7f2fe78bSCy Schubert  */
1066*7f2fe78bSCy Schubert long k5_path_split(const char *path, char **parent_out, char **basename_out);
1067*7f2fe78bSCy Schubert 
1068*7f2fe78bSCy Schubert /*
1069*7f2fe78bSCy Schubert  * Compose two path components, inserting the platform-appropriate path
1070*7f2fe78bSCy Schubert  * separator if needed.  If path2 is an absolute path, path1 will be discarded
1071*7f2fe78bSCy Schubert  * and path_out will be a copy of path2.  Returns 0 on success or ENOMEM on
1072*7f2fe78bSCy Schubert  * allocation failure.
1073*7f2fe78bSCy Schubert  */
1074*7f2fe78bSCy Schubert long k5_path_join(const char *path1, const char *path2, char **path_out);
1075*7f2fe78bSCy Schubert 
1076*7f2fe78bSCy Schubert /* Return 1 if path is absolute, 0 if it is relative. */
1077*7f2fe78bSCy Schubert int k5_path_isabs(const char *path);
1078*7f2fe78bSCy Schubert 
1079*7f2fe78bSCy Schubert /*
1080*7f2fe78bSCy Schubert  * Localization macros.  If we have gettext, define _ appropriately for
1081*7f2fe78bSCy Schubert  * translating a string.  If we do not have gettext, define _ and
1082*7f2fe78bSCy Schubert  * bindtextdomain as no-ops.  N_ is always a no-op; it marks a string for
1083*7f2fe78bSCy Schubert  * extraction to pot files but does not translate it.
1084*7f2fe78bSCy Schubert  */
1085*7f2fe78bSCy Schubert #ifdef ENABLE_NLS
1086*7f2fe78bSCy Schubert #include <libintl.h>
1087*7f2fe78bSCy Schubert #define KRB5_TEXTDOMAIN "mit-krb5"
1088*7f2fe78bSCy Schubert #define _(s) dgettext(KRB5_TEXTDOMAIN, s)
1089*7f2fe78bSCy Schubert #else
1090*7f2fe78bSCy Schubert #define _(s) s
1091*7f2fe78bSCy Schubert #define dgettext(d, m) m
1092*7f2fe78bSCy Schubert #define ngettext(m1, m2, n) (((n) == 1) ? m1 : m2)
1093*7f2fe78bSCy Schubert #define bindtextdomain(p, d)
1094*7f2fe78bSCy Schubert #endif
1095*7f2fe78bSCy Schubert #define N_(s) s
1096*7f2fe78bSCy Schubert 
1097*7f2fe78bSCy Schubert #if !defined(HAVE_GETOPT) || !defined(HAVE_UNISTD_H)
1098*7f2fe78bSCy Schubert /* Data objects imported from DLLs must be declared as such on Windows. */
1099*7f2fe78bSCy Schubert #if defined(_WIN32) && !defined(K5_GETOPT_C)
1100*7f2fe78bSCy Schubert #define K5_GETOPT_DECL __declspec(dllimport)
1101*7f2fe78bSCy Schubert #else
1102*7f2fe78bSCy Schubert #define K5_GETOPT_DECL
1103*7f2fe78bSCy Schubert #endif
1104*7f2fe78bSCy Schubert K5_GETOPT_DECL extern int k5_opterr;
1105*7f2fe78bSCy Schubert K5_GETOPT_DECL extern int k5_optind;
1106*7f2fe78bSCy Schubert K5_GETOPT_DECL extern int k5_optopt;
1107*7f2fe78bSCy Schubert K5_GETOPT_DECL extern char *k5_optarg;
1108*7f2fe78bSCy Schubert #define opterr k5_opterr
1109*7f2fe78bSCy Schubert #define optind k5_optind
1110*7f2fe78bSCy Schubert #define optopt k5_optopt
1111*7f2fe78bSCy Schubert #define optarg k5_optarg
1112*7f2fe78bSCy Schubert 
1113*7f2fe78bSCy Schubert extern int k5_getopt(int nargc, char * const nargv[], const char *ostr);
1114*7f2fe78bSCy Schubert #define getopt k5_getopt
1115*7f2fe78bSCy Schubert #endif /* HAVE_GETOPT */
1116*7f2fe78bSCy Schubert 
1117*7f2fe78bSCy Schubert #ifdef HAVE_GETOPT_LONG
1118*7f2fe78bSCy Schubert #include <getopt.h>
1119*7f2fe78bSCy Schubert #else
1120*7f2fe78bSCy Schubert 
1121*7f2fe78bSCy Schubert struct option
1122*7f2fe78bSCy Schubert {
1123*7f2fe78bSCy Schubert   const char *name;
1124*7f2fe78bSCy Schubert   int has_arg;
1125*7f2fe78bSCy Schubert   int *flag;
1126*7f2fe78bSCy Schubert   int val;
1127*7f2fe78bSCy Schubert };
1128*7f2fe78bSCy Schubert 
1129*7f2fe78bSCy Schubert #define no_argument       0
1130*7f2fe78bSCy Schubert #define required_argument 1
1131*7f2fe78bSCy Schubert #define optional_argument 2
1132*7f2fe78bSCy Schubert 
1133*7f2fe78bSCy Schubert extern int k5_getopt_long(int nargc, char **nargv, char *options,
1134*7f2fe78bSCy Schubert                           struct option *long_options, int *index);
1135*7f2fe78bSCy Schubert #define getopt_long k5_getopt_long
1136*7f2fe78bSCy Schubert #endif /* HAVE_GETOPT_LONG */
1137*7f2fe78bSCy Schubert 
1138*7f2fe78bSCy Schubert #if defined(_WIN32)
1139*7f2fe78bSCy Schubert /* On Windows there is never a need to ignore the process environment. */
1140*7f2fe78bSCy Schubert #define secure_getenv getenv
1141*7f2fe78bSCy Schubert #elif !defined(HAVE_SECURE_GETENV)
1142*7f2fe78bSCy Schubert #define secure_getenv k5_secure_getenv
1143*7f2fe78bSCy Schubert extern char *k5_secure_getenv(const char *name);
1144*7f2fe78bSCy Schubert #endif
1145*7f2fe78bSCy Schubert 
1146*7f2fe78bSCy Schubert /* Set *fnames_out to a null-terminated list of filenames within dirname,
1147*7f2fe78bSCy Schubert  * sorted according to strcmp().  Return 0 on success, or ENOENT/ENOMEM. */
1148*7f2fe78bSCy Schubert int k5_dir_filenames(const char *dirname, char ***fnames_out);
1149*7f2fe78bSCy Schubert void k5_free_filenames(char **fnames);
1150*7f2fe78bSCy Schubert 
1151*7f2fe78bSCy Schubert #endif /* K5_PLATFORM_H */
1152