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