1 /* -*- mode: c; indent-tabs-mode: nil -*- */
2 /* include/k5-platform.h */
4 * Copyright 2003, 2004, 2005, 2007, 2008, 2009 Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
28 * Some platform-dependent definitions to sync up the C support level.
29 * Some to a C99-ish level, some related utility code.
32 * + [u]int{8,16,32}_t types
33 * + 64-bit types and load/store code
35 * + shared library init/fini hooks
36 * + consistent getpwnam/getpwuid interfaces
37 * + va_copy fudged if not provided
39 * + _, N_, dgettext, bindtextdomain, setlocale (for localization)
56 #define CAN_COPY_VA_LIST
59 #if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
60 #include <TargetConditionals.h>
63 /* Initialization and finalization function support for libraries.
65 At top level, before the functions are defined or even declared:
66 MAKE_INIT_FUNCTION(init_fn);
67 MAKE_FINI_FUNCTION(fini_fn);
69 int init_fn(void) { ... }
70 void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... }
71 In code, in the same file:
72 err = CALL_INIT_FUNCTION(init_fn);
74 To trigger or verify the initializer invocation from another file,
75 a helper function must be created.
77 This model handles both the load-time execution (Windows) and
78 delayed execution (pthread_once) approaches, and should be able to
79 guarantee in both cases that the init function is run once, in one
80 thread, before other stuff in the library is done; furthermore, the
81 finalization code should only run if the initialization code did.
82 (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via
83 another function hidden in macros, but this is hairy enough
86 The init_fn and fini_fn names should be chosen such that any
87 exported names staring with those names, and optionally followed by
88 additional characters, fits in with any namespace constraints on
89 the library in question.
92 There's also PROGRAM_EXITING() currently always defined as zero.
93 If there's some trivial way to find out if the fini function is
94 being called because the program that the library is linked into is
95 exiting, we can just skip all the work because the resources are
96 about to be freed up anyways. Generally this is likely to be the
97 same as distinguishing whether the library was loaded dynamically
98 while the program was running, or loaded as part of program
99 startup. On most platforms, I don't think we can distinguish these
100 cases easily, and it's probably not worth expending any significant
101 effort. (Note in particular that atexit() won't do, because if the
102 library is explicitly loaded and unloaded, it would have to be able
103 to deregister the atexit callback function. Also, the system limit
104 on atexit callbacks may be small.)
107 Implementation outline:
109 Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that
110 is sought at library build time, and code is added to invoke the
111 function when the library is unloaded. MAKE_INIT_FUNCTION does
112 likewise, but the function is invoked when the library is loaded,
113 and an extra variable is declared to hold an error code and a "yes
114 the initializer ran" flag. CALL_INIT_FUNCTION blows up if the flag
115 isn't set, otherwise returns the error code.
117 UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a
118 name derived from the function name, containing a k5_once_t
119 (pthread_once_t or int), an error code, and a pointer to the
120 function. The function itself is declared static, but the
121 associated variable has external linkage. CALL_INIT_FUNCTION
122 ensures thath the function is called exactly once (pthread_once or
123 just check the flag) and returns the stored error code (or the
126 (That's the basic idea. With some debugging assert() calls and
127 such, it's a bit more complicated. And we also need to handle
128 doing the pthread test at run time on systems where that works, so
129 we use the k5_once_t stuff instead.)
131 UNIX, with compiler support: MAKE_FINI_FUNCTION declares the
132 function as a destructor, and the run time linker support or
133 whatever will cause it to be invoked when the library is unloaded,
134 the program ends, etc.
136 UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with
137 a magic name that is sought at library build time, and linker
138 options are used to mark it as a finalization function for the
139 library. The symbol must be exported.
141 UNIX, no library finalization support: The finalization function
142 never runs, and we leak memory. Tough.
144 DELAY_INITIALIZER will be defined by the configure script if we
145 want to use k5_once instead of load-time initialization. That'll
146 be the preferred method on most systems except Windows, where we
147 have to initialize some mutexes.
152 For maximum flexibility in defining the macros, the function name
153 parameter should be a simple name, not even a macro defined as
154 another name. The function should have a unique name, and should
155 conform to whatever namespace is used by the library in question.
156 (We do have export lists, but (1) they're not used for all
157 platforms, and (2) they're not used for static libraries.)
159 If the macro expansion needs the function to have been declared, it
160 must include a declaration. If it is not necessary for the symbol
161 name to be exported from the object file, the macro should declare
162 it as "static". Hence the signature must exactly match "void
163 foo(void)". (ANSI C allows a static declaration followed by a
164 non-static one; the result is internal linkage.) The macro
165 expansion has to come before the function, because gcc apparently
166 won't act on "__attribute__((constructor))" if it comes after the
169 This is going to be compiler- and environment-specific, and may
170 require some support at library build time, and/or "asm"
171 statements. But through macro expansion and auxiliary functions,
172 we should be able to handle most things except #pragma.
174 It's okay for this code to require that the library be built
175 with the same compiler and compiler options throughout, but
176 we shouldn't require that the library and application use the
179 For static libraries, we don't really care about cleanup too much,
180 since it's all memory handling and mutex allocation which will all
181 be cleaned up when the program exits. Thus, it's okay if gcc-built
182 static libraries don't play nicely with cc-built executables when
183 it comes to static constructors, just as long as it doesn't cause
186 For dynamic libraries on UNIX, we'll use pthread_once-type support
187 to do delayed initialization, so if finalization can't be made to
188 work, we'll only have memory leaks in a load/use/unload cycle. If
189 anyone (like, say, the OS vendor) complains about this, they can
190 tell us how to get a shared library finalization function invoked
193 Currently there's --disable-delayed-initialization for preventing
194 the initialization from being delayed on UNIX, but that's mainly
195 just for testing the linker options for initialization, and will
196 probably be removed at some point. */
200 # define JOIN__2_2(A,B) A ## _ ## _ ## B
201 # define JOIN__2(A,B) JOIN__2_2(A,B)
203 /* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set,
204 always provide a function by the expected name, even if we're
205 delaying initialization. */
207 #if defined(DELAY_INITIALIZER)
209 /* Run the initialization code during program execution, at the latest
210 possible moment. This means multiple threads may be active. */
211 # include "k5-thread.h"
212 typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t;
213 # ifdef USE_LINKER_INIT_OPTION
214 # define MAYBE_DUMMY_INIT(NAME) \
215 void JOIN__2(NAME, auxinit) () { }
217 # define MAYBE_DUMMY_INIT(NAME)
220 /* Do it in macro form so we get the file/line of the invocation if
221 the assertion fails. */
222 # define k5_call_init_function(I) \
224 k5_init_t *k5int_i = (I); \
225 int k5int_err = k5_once(&k5int_i->once, k5int_i->fn); \
228 : (assert(k5int_i->did_run != 0), k5int_i->error)); \
230 # define MAYBE_DEFINE_CALLINIT_FUNCTION
232 # define MAYBE_DEFINE_CALLINIT_FUNCTION \
233 static inline int k5_call_init_function(k5_init_t *i) \
236 err = k5_once(&i->once, i->fn); \
239 assert (i->did_run != 0); \
243 # define MAKE_INIT_FUNCTION(NAME) \
244 static int NAME(void); \
245 MAYBE_DUMMY_INIT(NAME) \
246 /* forward declaration for use in initializer */ \
247 static void JOIN__2(NAME, aux) (void); \
248 static k5_init_t JOIN__2(NAME, once) = \
249 { K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) }; \
250 MAYBE_DEFINE_CALLINIT_FUNCTION \
251 static void JOIN__2(NAME, aux) (void) \
253 JOIN__2(NAME, once).did_run = 1; \
254 JOIN__2(NAME, once).error = NAME(); \
256 /* so ';' following macro use won't get error */ \
257 static int NAME(void)
258 # define CALL_INIT_FUNCTION(NAME) \
259 k5_call_init_function(& JOIN__2(NAME, once))
260 /* This should be called in finalization only, so we shouldn't have
261 multiple active threads mucking around in our library at this
262 point. So ignore the once_t object and just look at the flag.
264 XXX Could we have problems with memory coherence between processors
265 if we don't invoke mutex/once routines? Probably not, the
266 application code should already be coordinating things such that
267 the library code is not in use by this point, and memory
268 synchronization will be needed there. */
269 # define INITIALIZER_RAN(NAME) \
270 (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0)
272 # define PROGRAM_EXITING() (0)
274 #elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS)
276 /* Run initializer at load time, via GCC/C++ hook magic. */
278 # ifdef USE_LINKER_INIT_OPTION
279 /* Both gcc and linker option?? Favor gcc. */
280 # define MAYBE_DUMMY_INIT(NAME) \
281 void JOIN__2(NAME, auxinit) () { }
283 # define MAYBE_DUMMY_INIT(NAME)
286 typedef struct { int error; unsigned char did_run; } k5_init_t;
287 # define MAKE_INIT_FUNCTION(NAME) \
288 MAYBE_DUMMY_INIT(NAME) \
289 static k5_init_t JOIN__2(NAME, ran) \
291 static void JOIN__2(NAME, aux)(void) \
292 __attribute__((constructor)); \
293 static int NAME(void); \
294 static void JOIN__2(NAME, aux)(void) \
296 JOIN__2(NAME, ran).error = NAME(); \
297 JOIN__2(NAME, ran).did_run = 3; \
299 static int NAME(void)
300 # define CALL_INIT_FUNCTION(NAME) \
301 (JOIN__2(NAME, ran).did_run == 3 \
302 ? JOIN__2(NAME, ran).error \
304 # define INITIALIZER_RAN(NAME) (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0)
306 # define PROGRAM_EXITING() (0)
308 #elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32)
310 /* Run initializer at load time, via linker magic, or in the
311 case of WIN32, win_glue.c hard-coded knowledge. */
312 typedef struct { int error; unsigned char did_run; } k5_init_t;
313 # define MAKE_INIT_FUNCTION(NAME) \
314 static k5_init_t JOIN__2(NAME, ran) \
316 static int NAME(void); \
317 void JOIN__2(NAME, auxinit)() \
319 JOIN__2(NAME, ran).error = NAME(); \
320 JOIN__2(NAME, ran).did_run = 3; \
322 static int NAME(void)
323 # define CALL_INIT_FUNCTION(NAME) \
324 (JOIN__2(NAME, ran).did_run == 3 \
325 ? JOIN__2(NAME, ran).error \
327 # define INITIALIZER_RAN(NAME) \
328 (JOIN__2(NAME, ran).error == 0)
330 # define PROGRAM_EXITING() (0)
334 # error "Don't know how to do load-time initializers for this configuration."
336 # define PROGRAM_EXITING() (0)
342 #if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32)
343 /* If we're told the linker option will be used, it doesn't really
344 matter what compiler we're using. Do it the same way
349 /* On HP-UX, we need this auxiliary function. At dynamic load or
350 unload time (but *not* program startup and termination for
351 link-time specified libraries), the linker-indicated function
352 is called with a handle on the library and a flag indicating
353 whether it's being loaded or unloaded.
355 The "real" fini function doesn't need to be exported, so
358 As usual, the final declaration is just for syntactic
359 convenience, so the top-level invocation of this macro can be
360 followed by a semicolon. */
363 # define MAKE_FINI_FUNCTION(NAME) \
364 static void NAME(void); \
365 void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \
366 void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \
367 static void NAME(void)
369 # else /* not hpux */
371 # define MAKE_FINI_FUNCTION(NAME) \
376 #elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS)
377 /* If we're using gcc, if the C++ support works, the compiler should
378 build executables and shared libraries that support the use of
379 static constructors and destructors. The C compiler supports a
380 function attribute that makes use of the same facility as C++.
382 XXX How do we know if the C++ support actually works? */
383 # define MAKE_FINI_FUNCTION(NAME) \
384 static void NAME(void) __attribute__((destructor))
386 #elif !defined(SHARED)
388 /* In this case, we just don't care about finalization.
390 The code will still define the function, but we won't do anything
391 with it. Annoying: This may generate unused-function warnings. */
393 # define MAKE_FINI_FUNCTION(NAME) \
394 static void NAME(void)
398 # error "Don't know how to do unload-time finalization for this configuration."
403 /* 64-bit support: krb5_ui_8 and krb5_int64.
405 This should move to krb5.h eventually, but without the namespace
406 pollution from the autoconf macros. */
407 #if defined(HAVE_STDINT_H) || defined(HAVE_INTTYPES_H)
408 # ifdef HAVE_STDINT_H
411 # ifdef HAVE_INTTYPES_H
412 # include <inttypes.h>
414 # define INT64_TYPE int64_t
415 # define UINT64_TYPE uint64_t
416 #elif defined(_WIN32)
417 # define INT64_TYPE signed __int64
418 # define UINT64_TYPE unsigned __int64
419 #else /* not Windows, and neither stdint.h nor inttypes.h */
420 # define INT64_TYPE signed long long
421 # define UINT64_TYPE unsigned long long
425 # define SIZE_MAX ((size_t)((size_t)0 - 1))
429 # define UINT64_MAX ((UINT64_TYPE)((UINT64_TYPE)0 - 1))
433 # define SSIZE_MAX ((ssize_t)(SIZE_MAX/2))
436 /* Read and write integer values as (unaligned) octet strings in
437 specific byte orders. Add per-platform optimizations as
442 #elif HAVE_MACHINE_ENDIAN_H
443 # include <machine/endian.h>
445 /* Check for BIG/LITTLE_ENDIAN macros. If exactly one is defined, use
446 it. If both are defined, then BYTE_ORDER should be defined and
447 match one of them. Try those symbols, then try again with an
448 underscore prefix. */
449 #if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
450 # if BYTE_ORDER == BIG_ENDIAN
453 # if BYTE_ORDER == LITTLE_ENDIAN
456 #elif defined(BIG_ENDIAN)
458 #elif defined(LITTLE_ENDIAN)
460 #elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
461 # if _BYTE_ORDER == _BIG_ENDIAN
464 # if _BYTE_ORDER == _LITTLE_ENDIAN
467 #elif defined(_BIG_ENDIAN)
469 #elif defined(_LITTLE_ENDIAN)
471 #elif defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
473 #elif defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
476 #if !defined(K5_BE) && !defined(K5_LE)
477 /* Look for some architectures we know about.
479 MIPS can use either byte order, but the preprocessor tells us which
480 mode we're compiling for. The GCC config files indicate that
481 variants of Alpha and IA64 might be out there with both byte
482 orders, but until we encounter the "wrong" ones in the real world,
483 just go with the default (unless there are cpp predefines to help
486 As far as I know, only PDP11 and ARM (which we don't handle here)
487 have strange byte orders where an 8-byte value isn't laid out as
488 either 12345678 or 87654321. */
489 # if defined(__i386__) || defined(_MIPSEL) || defined(__alpha__) || (defined(__ia64__) && !defined(__hpux))
492 # if defined(__hppa__) || defined(__rs6000__) || defined(__sparc__) || defined(_MIPSEB) || defined(__m68k__) || defined(__sparc64__) || defined(__ppc__) || defined(__ppc64__) || (defined(__hpux) && defined(__ia64__))
496 #if defined(K5_BE) && defined(K5_LE)
497 # error "oops, check the byte order macros"
500 /* Optimize for GCC on platforms with known byte orders.
502 GCC's packed structures can be written to with any alignment; the
503 compiler will use byte operations, unaligned-word operations, or
504 normal memory ops as appropriate for the architecture.
506 This assumes the availability of uint##_t types, which should work
507 on most of our platforms except Windows, where we're not using
510 # define PUT(SIZE,PTR,VAL) (((struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i = (VAL))
511 # define GET(SIZE,PTR) (((const struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i)
512 # define PUTSWAPPED(SIZE,PTR,VAL) PUT(SIZE,PTR,SWAP##SIZE(VAL))
513 # define GETSWAPPED(SIZE,PTR) SWAP##SIZE(GET(SIZE,PTR))
515 /* To do: Define SWAP16, SWAP32, SWAP64 macros to byte-swap values
516 with the indicated numbers of bits.
518 Linux: byteswap.h, bswap_16 etc.
520 Mac OS X: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong}
521 NetBSD: sys/bswap.h, bswap16 etc. */
523 #if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16)
524 # include <byteswap.h>
525 # define SWAP16 bswap_16
526 # define SWAP32 bswap_32
527 # ifdef HAVE_BSWAP_64
528 # define SWAP64 bswap_64
531 # include <architecture/byte_order.h>
532 # if 0 /* This causes compiler warnings. */
533 # define SWAP16 OSSwapInt16
535 # define SWAP16 k5_swap16
536 static inline unsigned int k5_swap16 (unsigned int x) {
538 return (x >> 8) | ((x & 0xff) << 8);
541 # define SWAP32 OSSwapInt32
542 # define SWAP64 OSSwapInt64
543 #elif defined(HAVE_SYS_BSWAP_H)
544 /* XXX NetBSD/x86 5.0.1 defines bswap16 and bswap32 as inline
545 functions only, so autoconf doesn't pick up on their existence.
546 So, no feature macro test for them here. The 64-bit version isn't
547 inline at all, though, for whatever reason. */
548 # include <sys/bswap.h>
549 # define SWAP16 bswap16
550 # define SWAP32 bswap32
551 /* However, bswap64 causes lots of warnings about 'long long'
552 constants; probably only on 32-bit platforms. */
553 # if LONG_MAX > 0x7fffffffL
554 # define SWAP64 bswap64
558 /* Note that on Windows at least this file can be included from C++
559 source, so casts *from* void* are required. */
561 store_16_be (unsigned int val, void *vp)
563 unsigned char *p = (unsigned char *) vp;
564 #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
566 #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
567 PUTSWAPPED(16,p,val);
569 p[0] = (val >> 8) & 0xff;
570 p[1] = (val ) & 0xff;
574 store_32_be (unsigned int val, void *vp)
576 unsigned char *p = (unsigned char *) vp;
577 #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
579 #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
580 PUTSWAPPED(32,p,val);
582 p[0] = (val >> 24) & 0xff;
583 p[1] = (val >> 16) & 0xff;
584 p[2] = (val >> 8) & 0xff;
585 p[3] = (val ) & 0xff;
589 store_64_be (UINT64_TYPE val, void *vp)
591 unsigned char *p = (unsigned char *) vp;
592 #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
594 #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
595 PUTSWAPPED(64,p,val);
597 p[0] = (unsigned char)((val >> 56) & 0xff);
598 p[1] = (unsigned char)((val >> 48) & 0xff);
599 p[2] = (unsigned char)((val >> 40) & 0xff);
600 p[3] = (unsigned char)((val >> 32) & 0xff);
601 p[4] = (unsigned char)((val >> 24) & 0xff);
602 p[5] = (unsigned char)((val >> 16) & 0xff);
603 p[6] = (unsigned char)((val >> 8) & 0xff);
604 p[7] = (unsigned char)((val ) & 0xff);
607 static inline unsigned short
608 load_16_be (const void *cvp)
610 const unsigned char *p = (const unsigned char *) cvp;
611 #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
613 #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
614 return GETSWAPPED(16,p);
616 return (p[1] | (p[0] << 8));
619 static inline unsigned int
620 load_32_be (const void *cvp)
622 const unsigned char *p = (const unsigned char *) cvp;
623 #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
625 #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
626 return GETSWAPPED(32,p);
628 return (p[3] | (p[2] << 8)
629 | ((uint32_t) p[1] << 16)
630 | ((uint32_t) p[0] << 24));
633 static inline UINT64_TYPE
634 load_64_be (const void *cvp)
636 const unsigned char *p = (const unsigned char *) cvp;
637 #if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
639 #elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
640 return GETSWAPPED(64,p);
642 return ((UINT64_TYPE)load_32_be(p) << 32) | load_32_be(p+4);
646 store_16_le (unsigned int val, void *vp)
648 unsigned char *p = (unsigned char *) vp;
649 #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
651 #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
652 PUTSWAPPED(16,p,val);
654 p[1] = (val >> 8) & 0xff;
655 p[0] = (val ) & 0xff;
659 store_32_le (unsigned int val, void *vp)
661 unsigned char *p = (unsigned char *) vp;
662 #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
664 #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
665 PUTSWAPPED(32,p,val);
667 p[3] = (val >> 24) & 0xff;
668 p[2] = (val >> 16) & 0xff;
669 p[1] = (val >> 8) & 0xff;
670 p[0] = (val ) & 0xff;
674 store_64_le (UINT64_TYPE val, void *vp)
676 unsigned char *p = (unsigned char *) vp;
677 #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
679 #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
680 PUTSWAPPED(64,p,val);
682 p[7] = (unsigned char)((val >> 56) & 0xff);
683 p[6] = (unsigned char)((val >> 48) & 0xff);
684 p[5] = (unsigned char)((val >> 40) & 0xff);
685 p[4] = (unsigned char)((val >> 32) & 0xff);
686 p[3] = (unsigned char)((val >> 24) & 0xff);
687 p[2] = (unsigned char)((val >> 16) & 0xff);
688 p[1] = (unsigned char)((val >> 8) & 0xff);
689 p[0] = (unsigned char)((val ) & 0xff);
692 static inline unsigned short
693 load_16_le (const void *cvp)
695 const unsigned char *p = (const unsigned char *) cvp;
696 #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
698 #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
699 return GETSWAPPED(16,p);
701 return (p[0] | (p[1] << 8));
704 static inline unsigned int
705 load_32_le (const void *cvp)
707 const unsigned char *p = (const unsigned char *) cvp;
708 #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
710 #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
711 return GETSWAPPED(32,p);
713 return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
716 static inline UINT64_TYPE
717 load_64_le (const void *cvp)
719 const unsigned char *p = (const unsigned char *) cvp;
720 #if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
722 #elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
723 return GETSWAPPED(64,p);
725 return ((UINT64_TYPE)load_32_le(p+4) << 32) | load_32_le(p);
730 #define UINT16_TYPE unsigned __int16
731 #define UINT32_TYPE unsigned __int32
733 #define UINT16_TYPE uint16_t
734 #define UINT32_TYPE uint32_t
738 store_16_n (unsigned int val, void *vp)
744 store_32_n (unsigned int val, void *vp)
750 store_64_n (UINT64_TYPE val, void *vp)
755 static inline unsigned short
756 load_16_n (const void *p)
762 static inline unsigned int
763 load_32_n (const void *p)
769 static inline UINT64_TYPE
770 load_64_n (const void *p)
779 /* Assume for simplicity that these swaps are identical. */
780 static inline UINT64_TYPE
781 k5_htonll (UINT64_TYPE val)
785 #elif defined K5_LE && defined SWAP64
788 return load_64_be ((unsigned char *)&val);
791 static inline UINT64_TYPE
792 k5_ntohll (UINT64_TYPE val)
794 return k5_htonll (val);
797 /* Make the interfaces to getpwnam and getpwuid consistent.
798 Model the wrappers on the POSIX thread-safe versions, but
799 use the unsafe system versions if the safe ones don't exist
800 or we can't figure out their interfaces. */
802 /* int k5_getpwnam_r(const char *, blah blah) */
803 #ifdef HAVE_GETPWNAM_R
804 # ifndef GETPWNAM_R_4_ARGS
806 # define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
807 (getpwnam_r(NAME,REC,BUF,BUFSIZE,OUT) == 0 \
808 ? (*(OUT) == NULL ? -1 : 0) : -1)
811 # ifdef GETPWNAM_R_RETURNS_INT
812 # define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
813 (getpwnam_r(NAME,REC,BUF,BUFSIZE) == 0 \
814 ? (*(OUT) = REC, 0) \
815 : (*(OUT) = NULL, -1))
817 # define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
818 (*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
821 #else /* no getpwnam_r, or can't figure out #args or return type */
822 /* Will get warnings about unused variables. */
823 # define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
824 (*(OUT) = getpwnam(NAME), *(OUT) == NULL ? -1 : 0)
827 /* int k5_getpwuid_r(uid_t, blah blah) */
828 #ifdef HAVE_GETPWUID_R
829 # ifndef GETPWUID_R_4_ARGS
831 # define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
832 (getpwuid_r(UID,REC,BUF,BUFSIZE,OUT) == 0 \
833 ? (*(OUT) == NULL ? -1 : 0) : -1)
835 /* POSIX drafts? Yes, I mean to test GETPWNAM... here. Less junk to
836 do at configure time. */
837 # ifdef GETPWNAM_R_RETURNS_INT
838 # define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
839 (getpwuid_r(UID,REC,BUF,BUFSIZE) == 0 \
840 ? (*(OUT) = REC, 0) \
841 : (*(OUT) = NULL, -1))
843 # define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
844 (*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
847 #else /* no getpwuid_r, or can't figure out #args or return type */
848 /* Will get warnings about unused variables. */
849 # define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
850 (*(OUT) = getpwuid(UID), *(OUT) == NULL ? -1 : 0)
853 /* Ensure, if possible, that the indicated file descriptor won't be
854 kept open if we exec another process (e.g., launching a ccapi
855 server). If we don't know how to do it... well, just go about our
856 business. Probably most callers won't check the return status
861 set_cloexec_fd(int fd)
865 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0)
868 if (fcntl(fd, F_SETFD, 1) != 0)
876 set_cloexec_file(FILE *f)
878 return set_cloexec_fd(fileno(f));
881 /* Macros make the Sun compiler happier, and all variants of this do a
882 single evaluation of the argument, and fcntl and fileno should
883 produce reasonable error messages on type mismatches, on any system
887 # define set_cloexec_fd(FD) (fcntl((FD), F_SETFD, FD_CLOEXEC) ? errno : 0)
889 # define set_cloexec_fd(FD) (fcntl((FD), F_SETFD, 1) ? errno : 0)
892 # define set_cloexec_fd(FD) ((FD),0)
894 #define set_cloexec_file(F) set_cloexec_fd(fileno(F))
899 /* Since the original ANSI C spec left it undefined whether or
900 how you could copy around a va_list, C 99 added va_copy.
901 For old implementations, let's do our best to fake it.
903 XXX Doesn't yet handle implementations with __va_copy (early draft)
904 or GCC's __builtin_va_copy. */
905 #if defined(HAS_VA_COPY) || defined(va_copy)
907 #elif defined(CAN_COPY_VA_LIST)
908 #define va_copy(dest, src) ((dest) = (src))
910 /* Assume array type, but still simply copyable.
912 There is, theoretically, the possibility that va_start will
913 allocate some storage pointed to by the va_list, and in that case
914 we'll just lose. If anyone cares, we could try to devise a test
916 #define va_copy(dest, src) memcmp(dest, src, sizeof(va_list))
919 /* Provide strlcpy/strlcat interfaces. */
921 #define strlcpy krb5int_strlcpy
922 #define strlcat krb5int_strlcat
923 extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz);
924 extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz);
927 /* Provide [v]asprintf interfaces. */
928 #ifndef HAVE_VSNPRINTF
931 vsnprintf(char *str, size_t size, const char *format, va_list args)
936 va_copy(args_copy, args);
937 length = _vscprintf(format, args_copy);
940 _vsnprintf(str, size, format, args);
944 snprintf(char *str, size_t size, const char *format, ...)
949 va_start(args, format);
950 n = vsnprintf(str, size, format, args);
954 #else /* not win32 */
955 #error We need an implementation of vsnprintf.
957 #endif /* no vsnprintf */
959 #ifndef HAVE_VASPRINTF
961 extern int krb5int_vasprintf(char **, const char *, va_list)
962 #if !defined(__cplusplus) && (__GNUC__ > 2)
963 __attribute__((__format__(__printf__, 2, 0)))
966 extern int krb5int_asprintf(char **, const char *, ...)
967 #if !defined(__cplusplus) && (__GNUC__ > 2)
968 __attribute__((__format__(__printf__, 2, 3)))
972 #define vasprintf krb5int_vasprintf
973 /* Assume HAVE_ASPRINTF iff HAVE_VASPRINTF. */
974 #define asprintf krb5int_asprintf
976 #elif defined(NEED_VASPRINTF_PROTO)
978 extern int vasprintf(char **, const char *, va_list)
979 #if !defined(__cplusplus) && (__GNUC__ > 2)
980 __attribute__((__format__(__printf__, 2, 0)))
983 extern int asprintf(char **, const char *, ...)
984 #if !defined(__cplusplus) && (__GNUC__ > 2)
985 __attribute__((__format__(__printf__, 2, 3)))
989 #endif /* have vasprintf and prototype? */
991 /* Return true if the snprintf return value RESULT reflects a buffer
992 overflow for the buffer size SIZE.
994 We cast the result to unsigned int for two reasons. First, old
995 implementations of snprintf (such as the one in Solaris 9 and
996 prior) return -1 on a buffer overflow. Casting the result to -1
997 will convert that value to UINT_MAX, which should compare larger
998 than any reasonable buffer size. Second, comparing signed and
999 unsigned integers will generate warnings with some compilers, and
1000 can have unpredictable results, particularly when the relative
1001 widths of the types is not known (size_t may be the same width as
1004 #define SNPRINTF_OVERFLOW(result, size) \
1005 ((unsigned int)(result) >= (size_t)(size))
1007 #ifndef HAVE_MKSTEMP
1008 extern int krb5int_mkstemp(char *);
1009 #define mkstemp krb5int_mkstemp
1012 extern void krb5int_zap(void *ptr, size_t len);
1015 * Localization macros. If we have gettext, define _ appropriately for
1016 * translating a string. If we do not have gettext, define _, bindtextdomain,
1017 * and setlocale as no-ops. N_ is always a no-op; it marks a string for
1018 * extraction to pot files but does not translate it.
1021 #include <libintl.h>
1023 #define KRB5_TEXTDOMAIN "mit-krb5"
1024 #define _(s) dgettext(KRB5_TEXTDOMAIN, s)
1027 #define dgettext(d, m) m
1028 #define bindtextdomain(p, d)
1029 #define setlocale(c, l)
1033 #endif /* K5_PLATFORM_H */