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

Re: Support for dynamically loadable backends




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

-- Luke

Subject: Support for dynamically loadable backends
To: heimdal-discuss@sics.se
Date: Tue, 17 Jun 2003 22:25:53 +1000

The attached patch adds support for dynamic loading of HDB backends
on platforms that support it.


-- Luke

Index: hdb.c
===================================================================
RCS file: /home/project/cvs/heimdal/lib/hdb/hdb.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 hdb.c
--- hdb.c	2002/08/11 23:53:58	1.1.1.1
+++ hdb.c	2003/06/17 12:25:55
@@ -33,8 +33,12 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id: hdb.c,v 1.1.1.1 2002/08/11 23:53:58 lukeh Exp $");
+RCSID("$Id: hdb.c,v 1.6 2002/11/04 12:00:01 lukeh 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,7 +209,62 @@
     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)
+{
+	const char *p;
+	void *dl;
+	char path[MAXPATHLEN], symbol[128];
+	static struct hdb_method method;
+	size_t len;
+
+	if (method.prefix != NULL) {
+		free((char *)method.prefix);
+	}
+
+	p = strchr((char *)filename, ':');
+	if (p != NULL) {
+		len = p - filename;
+		*rest = filename + len + 1;
+	} else {
+		len = strlen(filename);
+		*rest = "";
+	}
+
+	method.prefix = malloc(len + 1);
+	if (method.prefix == NULL) {
+		return NULL;
+	}
+
+	memcpy((char *)method.prefix, filename, len);
+	((char *)method.prefix)[len] = '\0';
+
+	snprintf(path, sizeof(path), LIBDIR "/hdb_%s.so", method.prefix);
+	snprintf(symbol, sizeof(symbol), "hdb_%s_create", method.prefix);
+
+	dl = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+	if (dl == NULL) {
+		krb5_errx(context, 1, "error loading dynamic module %s: %s\n", path, dlerror());
+		return NULL;
+	}
+
+	method.create = dlsym(dl, symbol);
+	if (method.create == NULL) {
+		krb5_errx(context, 1, "error finding symbol %s: %s\n", symbol, dlerror());
+		dlclose(dl);
+		return NULL;
+	}
+	
+	return &method;
+}
+#endif /* HAVE_DLOPEN */
+
+/*
  * find the relevant method for `filename', returning a pointer to the
  * rest in `rest'.
  * return NULL if there's no such method.
@@ -233,6 +292,10 @@
     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);
+    if (h == NULL)
+#endif
     h = find_method (filename, &residual);
     if (h == NULL)
 	krb5_errx(context, 1, "No database support! (hdb_create)");

--
Luke Howard | PADL Software Pty Ltd | www.padl.com