diff options
| author | Ken Raeburn <raeburn@mit.edu> | 2006-03-07 20:45:24 +0000 |
|---|---|---|
| committer | Ken Raeburn <raeburn@mit.edu> | 2006-03-07 20:45:24 +0000 |
| commit | 8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b (patch) | |
| tree | 68c4097fc6650d9d2952fdc0b242263b60ae7f95 /src/util | |
| parent | ca39d95f3cb9681664d3761f4c0c2ec23d36dfd3 (diff) | |
| download | krb5-8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b.tar.gz krb5-8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b.tar.xz krb5-8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b.zip | |
Merge from plugin branch
Add plugin support:
- plugin routines in support library (may break windows build!)
- plugin support in KDC location code
- sample Python-based plugin for KDC location, not built without
tweaking sources
- changed service location interface to use an enum instead of passing
profile string and DNS strings and port numbers
- changed pathnames for plugin locations, including kdb back end
- remove locate_service from accessor API
Also, do build shared libraries for Darwin just like any other UNIX box.
Not present yet:
- use new plugin interface for kdb back end
- Windows support
- Mac bundle support (but dlopen support works)
- search path for libkrb5 plugins (only one hard-coded directory for now)
- sorting of plugin collections for predictable ordering
See the various ChangeLogs for specifics.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17706 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util')
| -rw-r--r-- | src/util/profile/ChangeLog | 4 | ||||
| -rw-r--r-- | src/util/profile/Makefile.in | 2 | ||||
| -rw-r--r-- | src/util/support/ChangeLog | 8 | ||||
| -rw-r--r-- | src/util/support/Makefile.in | 6 | ||||
| -rw-r--r-- | src/util/support/libkrb5support.exports | 10 | ||||
| -rw-r--r-- | src/util/support/plugins.c | 339 |
6 files changed, 366 insertions, 3 deletions
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index cbb95706e..ea269e8e2 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,3 +1,7 @@ +2006-03-06 Ken Raeburn <raeburn@mit.edu> + + * Makefile.in (profile_tcl): Include $(LIBS). + 2005-10-21 Ken Raeburn <raeburn@mit.edu> * prof_file.c (profile_update_file_data): Drop test of diff --git a/src/util/profile/Makefile.in b/src/util/profile/Makefile.in index 067007d84..a2d4814c8 100644 --- a/src/util/profile/Makefile.in +++ b/src/util/profile/Makefile.in @@ -119,7 +119,7 @@ profile_tcl.o: $(srcdir)/profile_tcl.c profile.h profile_tcl: profile_tcl.o libprofile.a $(CC_LINK) -o profile_tcl profile_tcl.o \ $(TCL_MAYBE_RPATH) \ - -L../et -L../.. libprofile.a $(DEPLIBS) $(TCL_LIBS) + -L../et -L../.. libprofile.a $(DEPLIBS) $(TCL_LIBS) $(LIBS) clean-unix:: clean-libs clean-libobjs $(RM) $(PROGS) *.o *~ test_parse core prof_err.h \ diff --git a/src/util/support/ChangeLog b/src/util/support/ChangeLog index 7c3c3648e..4ec482f24 100644 --- a/src/util/support/ChangeLog +++ b/src/util/support/ChangeLog @@ -1,3 +1,11 @@ +2006-03-06 Ken Raeburn <raeburn@mit.edu> + + * plugins.c: New file. + * Makefile.in (LIBMAJOR): Update to 1. + (STLIBOBJS, LIBOBJS): Add new file. + (SHLIB_EXPLIBS): Add $(DL_LIB). + * libkrb5support.exports: Add new functions. + 2006-02-24 Jeffrey Altman <jaltman@mit.edu> * Makefile.in: support for 64-bit Windows builds diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in index 5abd3a27e..da71cad88 100644 --- a/src/util/support/Makefile.in +++ b/src/util/support/Makefile.in @@ -18,7 +18,7 @@ PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) LIBBASE=krb5support -LIBMAJOR=0 +LIBMAJOR=1 LIBMINOR=0 LIBINITFUNC=krb5int_thread_support_init @@ -27,11 +27,13 @@ LIBFINIFUNC=krb5int_thread_support_fini STLIBOBJS= \ threads.o \ init-addrinfo.o \ + plugins.o \ fake-addrinfo.o LIBOBJS= \ $(OUTPRE)threads.$(OBJEXT) \ $(OUTPRE)init-addrinfo.$(OBJEXT) \ + $(OUTPRE)plugins.$(OBJEXT) \ $(OUTPRE)fake-addrinfo.$(OBJEXT) STOBJLISTS=OBJS.ST @@ -46,7 +48,7 @@ SRCS=\ $(srcdir)/fake-addrinfo.c SHLIB_EXPDEPS = # Add -lm if dumping thread stats, for sqrt. -SHLIB_EXPLIBS= $(LIBS) +SHLIB_EXPLIBS= $(LIBS) $(DL_LIB) SHLIB_DIRS= SHLIB_RDIRS=$(KRB5_LIBDIR) diff --git a/src/util/support/libkrb5support.exports b/src/util/support/libkrb5support.exports index d06911d53..1d7bc717f 100644 --- a/src/util/support/libkrb5support.exports +++ b/src/util/support/libkrb5support.exports @@ -11,6 +11,16 @@ krb5int_gai_strerror krb5int_getnameinfo krb5int_in6addr_any krb5int_pthread_loaded +krb5int_open_plugin +krb5int_close_plugin +krb5int_get_plugin_data +krb5int_get_plugin_func +krb5int_open_plugin_dir +krb5int_close_plugin_dir +krb5int_get_plugin_dir_data +krb5int_get_plugin_dir_func +krb5int_free_plugin_dir_data +krb5int_free_plugin_dir_func krb5int_mutex_alloc krb5int_mutex_free krb5int_mutex_lock diff --git a/src/util/support/plugins.c b/src/util/support/plugins.c new file mode 100644 index 000000000..bc93aa2b4 --- /dev/null +++ b/src/util/support/plugins.c @@ -0,0 +1,339 @@ +/* + * util/support/plugins.c + * + * Copyright 2006 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Plugin module support, and shims around dlopen/whatever. + */ + +#include "k5-int.h" +#include <dlfcn.h> + +#include <stdarg.h> +static void Tprintf (const char *fmt, ...) +{ +#ifdef DEBUG + va_list va; + va_start (va, fmt); + vfprintf (stderr, fmt, va); + va_end (va); +#endif +} + +struct plugin_file_handle { +#if 1 + void *dlhandle; +#define NULL_HANDLE(X) ((X)->dlhandle == NULL) +#define MAKE_NULL_HANDLE(X) ((X)->dlhandle = NULL) +/* #elif _WIN32 ... */ +#else + char dummy; +#define NULL_HANDLE(X) (1) +#define MAKE_NULL_HANDLE(X) (0) +#endif +}; + +krb5_error_code KRB5_CALLCONV +krb5int_open_plugin (const char *filename, struct plugin_file_handle **h) +{ + struct plugin_file_handle *htmp; + void *handle; + + handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (handle == NULL) { + const char *e; + e = dlerror(); + /* XXX copy and save away */ + return ENOENT; /* XXX */ + } + htmp = malloc (sizeof (*htmp)); + if (htmp == NULL) { + int err = errno; + dlclose(handle); + return err; + } + *h = htmp; + htmp->dlhandle = handle; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5int_get_plugin_data (struct plugin_file_handle *h, const char *csymname, + void **ptr) +{ + void *sym; + /* XXX Do we need to add a leading "_" to the symbol name on any + modern platforms? */ + sym = dlsym(h->dlhandle, csymname); + if (sym == NULL) { + const char *e; + e = dlerror(); + return ENOENT; + } + *ptr = sym; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5int_get_plugin_func (struct plugin_file_handle *h, const char *csymname, + void (**ptr)()) +{ + /* This code should do for any systems where function and data + symbols are handled the same. Note that this means there's no + function version of (say) dlsym, *and* the symbol-prefix + handling is the same for both data and functions. (And the + casting we do here works, etc.) */ + void *dptr; + krb5_error_code err; + + err = krb5int_get_plugin_data (h, csymname, &dptr); + if (err == 0) + *ptr = (void (*)()) dptr; + return err; +} + +void KRB5_CALLCONV +krb5int_close_plugin (struct plugin_file_handle *h) +{ + dlclose(h->dlhandle); + h->dlhandle = NULL; + free (h); +} + +/* autoconf docs suggest using this preference order */ +#if HAVE_DIRENT_H || USE_DIRENT_H +#include <dirent.h> +#define NAMELEN(D) strlen((D)->d_name) +#else +#define dirent direct +#define NAMELEN(D) ((D)->d->namlen) +#if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +#elif HAVE_SYS_DIR_H +# include <sys/dir.h> +#elif HAVE_NDIR_H +# include <ndir.h> +#endif +#endif + +krb5_error_code KRB5_CALLCONV +krb5int_open_plugin_dir (const char *dirname, + struct plugin_dir_handle *dirhandle) +{ + /* Q: Should names be sorted in some way first? */ + DIR *dir; + struct dirent *d; + struct plugin_file_handle *h, *newh, handle; + int nh; + int error = 0; + char path[MAXPATHLEN]; + + h = NULL; + nh = 0; + Tprintf("opening plugin directory '%s' to scan...\n", dirname); + dir = opendir(dirname); + if (dir == NULL) { + error = errno; + Tprintf("-> error %d/%s\n", error, strerror(error)); + if (error == ENOENT) + return 0; + return error; + } + do { + size_t len; + struct stat statbuf; + + d = readdir (dir); + if (d == NULL) + break; + len = NAMELEN(d); + if (strlen(dirname) + len + 2 > sizeof(path)) + continue; + sprintf(path, "%s/%*s", dirname, (int) len, d->d_name); + /* Optimization: Linux includes a file type field in the + directory structure. */ + if (stat(path, &statbuf) < 0) { + Tprintf("stat(%s): %s\n", path, strerror(errno)); + continue; + } + if ((statbuf.st_mode & S_IFMT) != S_IFREG) { + Tprintf("stat(%s): not a regular file\n", path); + continue; + } + Tprintf("trying to dlopen '%s'\n", path); + handle.dlhandle = dlopen(path, RTLD_NOW | RTLD_GLOBAL); + if (handle.dlhandle == NULL) { + const char *e = dlerror(); + Tprintf("dlopen error: %s\n", e); + /* dlerror(); */ + continue; + } else { + Tprintf("dlopen succeeds: %p\n", handle.dlhandle); + } + newh = realloc (h, (nh+1) * sizeof(*h)); + if (newh == NULL) { + int i; + close_and_return_errno: + error = errno; + for (i = 0; i < nh; i++) + dlclose(h[i].dlhandle); + free(h); + return error; + } + h = newh; + h[nh] = handle; + nh++; + } while (1); + Tprintf("done scanning plugin directory\n"); + newh = realloc (h, (nh+1) * sizeof(*h)); + if (newh == NULL) + goto close_and_return_errno; + h = newh; + MAKE_NULL_HANDLE (&h[nh]); + dirhandle->files = h; + return 0; +} + +void KRB5_CALLCONV +krb5int_close_plugin_dir (struct plugin_dir_handle *dirhandle) +{ + struct plugin_file_handle *h; + if (dirhandle->files == NULL) + return; + for (h = dirhandle->files; !NULL_HANDLE (h); h++) { + dlclose (h->dlhandle); + } + free(dirhandle->files); + dirhandle->files = NULL; +} + +void KRB5_CALLCONV +krb5int_free_plugin_dir_data (void **ptrs) +{ + /* Nothing special to be done per pointer. */ + free(ptrs); +} + +krb5_error_code KRB5_CALLCONV +krb5int_get_plugin_dir_data (struct plugin_dir_handle *dirhandle, + const char *symname, + void ***ptrs) +{ + void **p, **newp, *sym; + int count, i, err; + + if (dirhandle == NULL) { + *ptrs = 0; + return 0; + } + + /* XXX Do we need to add a leading "_" to the symbol name on any + modern platforms? */ + + Tprintf("get_plugin_data_sym(%s)\n", symname); + p = 0; + count = 0; + for (i = 0; !NULL_HANDLE (&dirhandle->files[i]); i++) { + Tprintf(" -> dlsym(%p,%s)\n", dirhandle->files[i].dlhandle, symname); + sym = dlsym(dirhandle->files[i].dlhandle, symname); + if (sym == NULL) { + const char *e = dlerror(); + Tprintf(" -> %s\n", e); + continue; + } else { + Tprintf(" -> %p\n", sym); + } + newp = realloc (p, (count+1) * sizeof(*p)); + if (newp == NULL) { + realloc_failure: + err = errno; + free(p); + return err; + } + p = newp; + p[count] = sym; + count++; + } + newp = realloc(p, (count+1) * sizeof(*p)); + if (newp == NULL) + goto realloc_failure; + p = newp; + p[count] = NULL; + *ptrs = p; + { + i = 0; + do { + Tprintf(" p[%d] = %p\n", i, p[i]); + } while (p[i++]); + } + return 0; +} + +void KRB5_CALLCONV +krb5int_free_plugin_dir_func (void (**ptrs)(void)) +{ + /* Nothing special to be done per pointer. */ + free(ptrs); +} + +krb5_error_code KRB5_CALLCONV +krb5int_get_plugin_dir_func (struct plugin_dir_handle *dirhandle, + const char *symname, + void (***ptrs)(void)) +{ + void (**p)(void), (**newp)(void), (*sym)(void); + int count, i, err; + + if (dirhandle == NULL) { + *ptrs = 0; + return 0; + } + + /* XXX Do we need to add a leading "_" to the symbol name on any + modern platforms? */ + + p = 0; + count = 0; + for (i = 0; !NULL_HANDLE (&dirhandle->files[i]); i++) { + sym = (void(*)(void)) dlsym(dirhandle->files[i].dlhandle, symname); + if (sym == NULL) + continue; + newp = realloc (p, (count+1) * sizeof(*p)); + if (newp == NULL) { + realloc_failure: + err = errno; + free(p); + return err; + } + p = newp; + p[count] = sym; + count++; + } + newp = realloc(p, (count+1) * sizeof(*p)); + if (newp == NULL) + goto realloc_failure; + p[count] = NULL; + *ptrs = p; + return 0; +} |
