[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Support for dynamically loadable backends




Luke Howard <lukeh@PADL.COM> writes:

> Upon reviewing this I realised it's preferable to use krb5_errx()
> than fprintf(). See revised patch (attached).

Wont loading of non-dynamic modules fail then ? I think warnx is what you
want.

it the (untested) patch below ok with you ?

Love

Index: hdb.c
===================================================================
RCS file: /afs/pdc.kth.se/src/packages/kth-krb/SourceRepository/heimdal/lib/hdb/hdb.c,v
retrieving revision 1.44
diff -u -u -w -r1.44 hdb.c
--- hdb.c	9 Aug 2001 08:41:48 -0000	1.44
+++ hdb.c	26 Jun 2003 04:10:58 -0000
@@ -35,6 +35,10 @@
 
 RCSID("$Id: hdb.c,v 1.44 2001/08/09 08:41:48 assar Exp $");
 
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
 struct hdb_method {
     const char *prefix;
     krb5_error_code (*create)(krb5_context, HDB **, const char *filename);
@@ -205,6 +210,72 @@
     return ret;
 }
 
+#ifdef HAVE_DLOPEN
+
+ /*
+ * Load a dynamic backend from /usr/heimdal/lib/hdb_XXX.so,
+ * looking for the hdb_XXX_create symbol.
+ */
+
+static const struct hdb_method *
+find_dynamic_method (krb5_context context,
+		     const char *filename, 
+		     const char **rest)
+{
+    static struct hdb_method method;
+    char *prefix, *path, *symbol;
+    const char *p;
+    void *dl;
+    size_t len;
+    
+    dl = NULL;
+
+    p = strchr(filename, ':');
+    if (p != NULL) {
+	len = p - filename;
+	*rest = filename + len + 1;
+    } else {
+	len = strlen(filename);
+	*rest = "";
+    }
+    
+    prefix = strndup(filename, len);
+    if (prefix == NULL)
+	krb5_errx(context, 1, "out of memory");
+    
+    if (asprintf(&path, LIBDIR "/hdb_%s.so", prefix) == -1)
+	krb5_errx(context, 1, "out of memory");
+
+    dl = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+    if (dl == NULL) {
+	krb5_warnx(context, "error trying to load dynamic module %s: %s\n",
+		   path, dlerror());
+	free(prefix);
+	free(path);
+	return NULL;
+    }
+    free(path);
+    
+    if (asprintf(&symbol, "hdb_%s_create", prefix) == -1)
+	krb5_errx(context, 1, "out of memory");
+	
+    method.create = dlsym(dl, symbol);
+    if (method.create == NULL) {
+	krb5_warnx(context, "error finding symbol %s: %s\n", 
+		   symbol, dlerror());
+	dlclose(dl);
+	free(symbol);
+	free(prefix);
+	return NULL;
+    }
+    free(symbol);
+
+    method.prefix = prefix;
+
+    return &method;
+}
+#endif /* HAVE_DLOPEN */
+
 /*
  * find the relevant method for `filename', returning a pointer to the
  * rest in `rest'.
@@ -227,12 +298,16 @@
 krb5_error_code
 hdb_create(krb5_context context, HDB **db, const char *filename)
 {
-    const struct hdb_method *h;
+    const struct hdb_method *h = NULL;
     const char *residual;
 
     if(filename == NULL)
 	filename = HDB_DEFAULT_DB;
     krb5_add_et_list(context, initialize_hdb_error_table_r);
+#ifdef HAVE_DLOPEN
+    h = find_dynamic_method (context, filename, &residual);
+#endif
+    if (h == NULL)
     h = find_method (filename, &residual);
     if (h == NULL)
 	krb5_errx(context, 1, "No database support! (hdb_create)");

PGP signature