File: _lcmaps.h

package info (click to toggle)
lcmaps 1.6.6-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,016 kB
  • ctags: 1,428
  • sloc: sh: 11,191; ansic: 9,519; makefile: 530; lex: 184; perl: 92; yacc: 60
file content (225 lines) | stat: -rw-r--r-- 7,426 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#ifndef _LCMAPS_H
#define _LCMAPS_H

#ifdef LCMAPS_USE_DLOPEN
#include <dlfcn.h>
/* Needed for NULL */
#include <stdio.h>
#endif


/**
  \defgroup LcmapsHiddenInterface The dark side of the LCMAPS interface
  \brief This part of the interface should not be used or observed directly

  The macros and declarations in this section define most of the
  internal mechanics of the interface such as calling dlopen() and
  dlsym(). They are only meant to be used by the public part of the
  interface.  The documentation serves as an aid in development, and
  is at the very most useful as a (bad) example.

  \warning Reading beyond this point may cause severe damage to one's appreciation
  of C programming.

*/

/*!
  \file _lcmaps.h
  \brief LCMAPS programming interface
  \authors Grid Security Middleware Team, Nikhef

    The following macro soup is too long, overly complicated and hard
   to follow.  Here is why. An old bug in LCMAPS (actually, VOMS) was
   that it missed certain 'version' functions. Each component in gLite
   was required to have the functions getMajorVersion, getMinorVersion
   and getPatchVersion.  Early versions of LCMAPS did not export these
   functions and none of the VOMS versions ever did (or ever
   will). Some versions of LCMAPS called these functions assuming they
   came from the VOMS library; in truth, the calls resolved to the
   functions (under the same name, as C doesn't support scoping or
   namespacing) in the LCAS library.  In later versions of LCMAPS
   these calls were removed. This bug remained hidden for a long time
   as LCAS was always used in conjunction with LCMAPS. But when LCMAPS
   is used without LCAS, the above functions are no longer resolvable
   and calling them throws a run-time error. The workaround that is
   applied e.g. in gLExec is to load the LCAS library if an old
   version of LCMAPS is detected.

   Users of the interface that a) do not use LCAS in conjunction with
   LCMAPS and b) want to have the legacy behaviour of loading LCAS to
   provide the above missing functions should #define
   LCMAPS_UGLY_VERSION_BUG_HACK prior to including lcmaps.h.


   The logic followed by this macro is then as follows:

   - try to load the interface library with RTLD_NOW
   -  if this fails, try to reload with RTLD_LAZY
   -   if this also fails, the library is probably missing -> THE END
   -   else, load the helper library; dlsym the getMajorVersion function;
   -    if this fails, it's THE END
   -    otherwise reload (again) with RTLD_NOW. This could fail but shouldn't.

   \ingroup LcmapsHiddenInterface
 */

/**
   \brief The getMajorVersion prototype

   This function is there only for testing whether the loading of the library
   in combination with the helper library will succeed.
 */
typedef int getMajorVersion_t (void);

/**
   \brief the major version funtion, present in newer LCMAPS libraries

   This funtion is loaded if present and used (only once) to return the library version.
 */

typedef int lcmaps_get_major_version_t (void);

/**
   \brief the major version funtion, present in newer LCMAPS libraries

   This funtion is loaded if present and used (only once) to return the library minor version.
 */
typedef int lcmaps_get_minor_version_t (void);

/**
   \brief the major version funtion, present in newer LCMAPS libraries

   This funtion is loaded if present and used (only once) to return the library patchlevel version.
 */
typedef int lcmaps_get_patch_version_t (void);

# ifndef LCMAPS_USE_DLOPEN
lcmaps_get_major_version_t lcmaps_get_major_version;
lcmaps_get_minor_version_t lcmaps_get_minor_version;
lcmaps_get_patch_version_t lcmaps_get_patch_version;
#endif /* LCMAPS_USE_DLOPEN */

/**
   \brief Collection of members to be included in the handle struct
   The LCMAPS_HANDLE structure varies for each interface,
   but they have some members in common.
 */
#define LCMAPS_HANDLE_VERSION_MEMBERS			  \
    getMajorVersion_t *getMajorVersion;			  \
    lcmaps_get_major_version_t *lcmaps_get_major_version; \
    lcmaps_get_minor_version_t *lcmaps_get_minor_version; \
    lcmaps_get_patch_version_t *lcmaps_get_patch_version; \
    int majorversion,minorversion,patchversion

#ifdef LCMAPS_USE_DLOPEN

#define _LCMAPS_MAJOR_VERSION(l) ((l)->majorversion)
#define _LCMAPS_MINOR_VERSION(l) ((l)->minorversion)
#define _LCMAPS_PATCH_VERSION(l) ((l)->patchversion)

#define _LCMAPS_SET_LIBFILE_PATH(l,p) ((l)->libfilename = (p))
#define _LCMAPS_SET_HELPER_PATH(l,p) ((l)->helpername = (p))

#define LCMAPS_LOAD_FUNC(l,f)						\
    (									\
     dlerror(),								\
     (l)->f = (f ## _t *) dlsym(l->handle, #f),				\
     ((l)->errmsg = dlerror()) == NULL					\
    )

/* Calling a loaded function is generally done through the following functions */
#define _LCMAPS_CALL(l,f) ( (l)->f )

#define _LCMAPS_LOAD_INTERFACE(l,d) \
    ( ( (l)->handle = dlopen((l)->libfilename, (d) | RTLD_GLOBAL)) != NULL )

/* store the error message and raise the error flag */
#define _LCMAPS_FAIL(l) ( ((l)->errmsg = dlerror()), 0)
/* #define LCMAPS_SUCCESS(l) ((l)->errmsg = dlerror(), 1) */


#ifdef LCMAPS_UGLY_VERSION_BUG_HACK
#  define LCMAPS_FIXVOMSHACKSO "liblcas" LIBSUFF
#else
#  define LCMAPS_FIXVOMSHACKSO "libvomsfix" LIBSUFF
#endif

#define _LCMAPS_LOAD_HELPER(l)						\
    (									\
     (l)->helper = dlopen(LCMAPS_FIXVOMSHACKSO, RTLD_NOW | RTLD_GLOBAL)	\
    )

#define _LCMAPS_GET_VERSION_LEVEL(l,v)					\
    (									\
     (l)->v ## version =						\
	( LCMAPS_LOAD_FUNC(l, lcmaps_get_ ## v ## _version) ?		\
	  ( (l)->lcmaps_get_ ## v ## _version() ) :			\
	  0								\
	)								\
    )

#define _LCMAPS_GET_VERSIONS(l)					\
    (								\
     _LCMAPS_GET_VERSION_LEVEL(l,major),				\
     _LCMAPS_GET_VERSION_LEVEL(l,minor),				\
     _LCMAPS_GET_VERSION_LEVEL(l,patch),				\
     1								\
    )


/* loading the helper and finding getMajorVersion in case of an 'old' lcmaps */
#define _LCMAPS_LOAD_INTERFACE_WITH_HELPER(l)				\
    (									\
     _LCMAPS_LOAD_INTERFACE(l, RTLD_LAZY) &&				\
     _LCMAPS_LOAD_HELPER(l) &&						\
     LCMAPS_LOAD_FUNC(l, getMajorVersion) &&				\
     (dlclose((l)->handle) == 0) &&					\
     _LCMAPS_LOAD_INTERFACE(l,RTLD_NOW)					\
    )

#define _LCMAPS_LOAD_INTERFACE_WITH_FIX(l)				\
    (									\
     (									\
      ( _LCMAPS_LOAD_INTERFACE(l,RTLD_NOW)				\
	|| _LCMAPS_LOAD_INTERFACE_WITH_HELPER(l)			\
	) && _LCMAPS_GET_VERSIONS(l) )					\
     || _LCMAPS_FAIL(l)							\
    )

#define _LCMAPS_ERRMSG(l) (l->errmsg)

#define _LCMAPS_REQUIRE_FUNC(l,f) LCMAPS_LOAD_FUNC(l,f)

#define LCMAPS_CLOSE_HANDLE(l) \
    (							\
     dlerror(),						\
     ( (l)->handle ? dlclose((l)->handle) : 1),		\
     ( (l)->helper ? dlclose((l)->helper) : 1),		\
     ( (l)->handle = (l)->helper = NULL ),		\
     ( ( (l)->errmsg = dlerror() ) == NULL )		\
    )

#else /* LCMAPS_USE_DLOPEN */

#define _LCMAPS_MAJOR_VERSION(l) (lcmaps_get_major_version())
#define _LCMAPS_MINOR_VERSION(l) (lcmaps_get_minor_version())
#define _LCMAPS_PATCH_VERSION(l) (lcmaps_get_patch_version())

#define _LCMAPS_SET_LIBFILE_PATH(l,p) (1)
#define _LCMAPS_SET_HELPER_PATH(l,p) (1)

#define LCMAPS_LOAD_FUNC(l,f) (1)

#define _LCMAPS_REQUIRE_FUNC(l,f) (1)

#define _LCMAPS_CALL(l,f) ( f )

#define _LCMAPS_ERRMSG(l) "This build is broken, LCMAPS_USE_DLOPEN is undefined."


#define LCMAPS_CLOSE_HANDLE(l) (1)

#endif /* LCMAPS_USE_DLOPEN */

#endif /* _LCMAPS_H */