removing svn keyword $Id$ from all files
[strongswan.git] / src / libstrongswan / plugins / plugin_loader.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #define _GNU_SOURCE
17 #include "plugin_loader.h"
18
19 #include <string.h>
20 #include <dlfcn.h>
21 #include <limits.h>
22 #include <stdio.h>
23
24 #include <debug.h>
25 #include <utils/linked_list.h>
26 #include <plugins/plugin.h>
27
28 typedef struct private_plugin_loader_t private_plugin_loader_t;
29
30 /**
31 * private data of plugin_loader
32 */
33 struct private_plugin_loader_t {
34
35 /**
36 * public functions
37 */
38 plugin_loader_t public;
39
40 /**
41 * list of loaded plugins
42 */
43 linked_list_t *plugins;
44
45 /**
46 * names of loaded plugins
47 */
48 linked_list_t *names;
49 };
50
51 /**
52 * load a single plugin
53 */
54 static plugin_t* load_plugin(private_plugin_loader_t *this,
55 char *path, char *name)
56 {
57 char file[PATH_MAX];
58 void *handle;
59 plugin_t *plugin;
60 plugin_constructor_t constructor;
61
62 snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path, name);
63
64 handle = dlopen(file, RTLD_LAZY);
65 if (handle == NULL)
66 {
67 DBG1("loading plugin '%s' failed: %s", name, dlerror());
68 return NULL;
69 }
70 constructor = dlsym(handle, "plugin_create");
71 if (constructor == NULL)
72 {
73 DBG1("loading plugin '%s' failed: no plugin_create() function", name);
74 dlclose(handle);
75 return NULL;
76 }
77 plugin = constructor();
78 if (plugin == NULL)
79 {
80 DBG1("loading plugin '%s' failed: plugin_create() returned NULL", name);
81 dlclose(handle);
82 return NULL;
83 }
84 DBG2("plugin '%s' loaded successfully", name);
85
86 /* we do not store or free dlopen() handles, leak_detective requires
87 * the modules to keep loaded until leak report */
88 return plugin;
89 }
90
91 /**
92 * Implementation of plugin_loader_t.load_plugins.
93 */
94 static int load(private_plugin_loader_t *this, char *path, char *list)
95 {
96 plugin_t *plugin;
97 enumerator_t *enumerator;
98 char *token;
99 int count = 0;
100
101 enumerator = enumerator_create_token(list, " ", " ");
102 while (enumerator->enumerate(enumerator, &token))
103 {
104 plugin = load_plugin(this, path, token);
105 if (plugin)
106 { /* insert in front to destroy them in reverse order */
107 this->plugins->insert_last(this->plugins, plugin);
108 this->names->insert_last(this->names, strdup(token));
109 count++;
110 }
111 }
112 enumerator->destroy(enumerator);
113 return count;
114 }
115
116 /**
117 * Implementation of plugin_loader_t.unload
118 */
119 static void unload(private_plugin_loader_t *this)
120 {
121 plugin_t *plugin;
122 char *name;
123
124 while (this->plugins->remove_first(this->plugins,
125 (void**)&plugin) == SUCCESS)
126 {
127 plugin->destroy(plugin);
128 }
129 while (this->names->remove_first(this->names, (void**)&name) == SUCCESS)
130 {
131 free(name);
132 }
133 }
134
135 /**
136 * Implementation of plugin_loader_t.create_plugin_enumerator
137 */
138 static enumerator_t* create_plugin_enumerator(private_plugin_loader_t *this)
139 {
140 return this->names->create_enumerator(this->names);
141 }
142
143 /**
144 * Implementation of plugin_loader_t.destroy
145 */
146 static void destroy(private_plugin_loader_t *this)
147 {
148 this->plugins->destroy_offset(this->plugins, offsetof(plugin_t, destroy));
149 this->names->destroy_function(this->names, free);
150 free(this);
151 }
152
153 /*
154 * see header file
155 */
156 plugin_loader_t *plugin_loader_create()
157 {
158 private_plugin_loader_t *this = malloc_thing(private_plugin_loader_t);
159
160 this->public.load = (int(*)(plugin_loader_t*, char *path, char *prefix))load;
161 this->public.unload = (void(*)(plugin_loader_t*))unload;
162 this->public.create_plugin_enumerator = (enumerator_t*(*)(plugin_loader_t*))create_plugin_enumerator;
163 this->public.destroy = (void(*)(plugin_loader_t*))destroy;
164
165 this->plugins = linked_list_create();
166 this->names = linked_list_create();
167
168 return &this->public;
169 }
170