Add first version of the plugin interface.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@18997 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2006-11-12 18:58:41 +00:00
parent 6d50466262
commit d4c6410532

230
lib/krb5/plugin.c Normal file
View File

@@ -0,0 +1,230 @@
/*
* Copyright (c) 2006 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id$");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <dirent.h>
struct krb5_plugin {
void *symbol;
void *dsohandle;
struct krb5_plugin *next;
};
struct plugin {
enum plugin_type type;
void *name;
void *symbol;
struct plugin *next;
};
static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER;
struct plugin *registered = NULL;
/*
*
*/
void *
_krb5_plugin_get_symbol(struct krb5_plugin *p)
{
return p->symbol;
}
struct krb5_plugin *
_krb5_plugin_get_next(struct krb5_plugin *p)
{
return p->next;
}
/*
*
*/
static krb5_error_code
loadlib(krb5_context context,
enum plugin_type type,
const char *name,
const char *lib,
struct krb5_plugin **e)
{
*e = calloc(1, sizeof(**e));
if (*e == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
(*e)->dsohandle = dlopen(lib, 0);
if ((*e)->dsohandle == NULL) {
free(*e);
krb5_set_error_string(context, "Failed to load %s: %s",
lib, dlerror());
return ENOMEM;
}
/* dlsym doesn't care about the type */
(*e)->symbol = dlsym((*e)->dsohandle, name);
if ((*e)->symbol == NULL) {
dlclose((*e)->dsohandle);
free(*e);
krb5_clear_error_string(context);
return ENOMEM;
}
return 0;
}
krb5_error_code
_krb5_plugin_register(krb5_context context,
enum plugin_type type,
const char *name,
void *symbol)
{
struct plugin *e;
e = calloc(1, sizeof(*e));
if (e == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
e->type = type;
e->name = strdup(name);
if (e->name == NULL) {
free(e);
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
e->symbol = symbol;
HEIMDAL_MUTEX_lock(&plugin_mutex);
e->next = registered;
registered = e;
HEIMDAL_MUTEX_unlock(&plugin_mutex);
return 0;
}
krb5_error_code
_krb5_plugin_find(krb5_context context,
enum plugin_type type,
const char *name,
struct krb5_plugin **list)
{
struct krb5_plugin *e;
struct plugin *p;
krb5_error_code ret;
const char *dir;
struct dirent *entry;
char *path;
DIR *d = NULL;
*list = NULL;
HEIMDAL_MUTEX_lock(&plugin_mutex);
for (p = registered; p != NULL; p = p->next) {
if (p->type != type || strcmp(p->name, name) != 0)
continue;
e = calloc(1, sizeof(*e));
if (e == NULL) {
HEIMDAL_MUTEX_unlock(&plugin_mutex);
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
goto out;
}
e->symbol = p->symbol;
e->dsohandle = NULL;
e->next = *list;
*list = e;
}
HEIMDAL_MUTEX_unlock(&plugin_mutex);
dir = "/usr/heimdal/lib/krb5/plugins";
/* XXX allow more directories */
d = opendir(dir);
if (d == NULL) {
if (*list == NULL) {
ret = errno;
krb5_set_error_string(context, "failed to open directory %s", dir);
return ret;
}
return 0;
}
while ((entry = readdir(d)) != NULL) {
asprintf(&path, "%s/%s", dir, entry->d_name);
if (path == NULL) {
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
goto out;
}
ret = loadlib(context, type, name, path, &e);
free(path);
if (ret)
continue;
e->next = *list;
*list = e;
}
closedir(d);
return 0;
out:
if (d)
closedir(d);
_krb5_plugin_free(*list);
*list = NULL;
return ret;
}
void
_krb5_plugin_free(struct krb5_plugin *list)
{
struct krb5_plugin *next;
while (list) {
next = list->next;
if (list->dsohandle)
dlclose(list->dsohandle);
free(list);
list = next;
}
}