fixed whitespace eating in plugin loader
[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 * $Id$
16 */
17
18 #include "plugin_loader.h"
19
20 #define _GNU_SOURCE
21 #include <string.h>
22 #include <dlfcn.h>
23 #include <limits.h>
24 #include <stdio.h>
25
26 #include <debug.h>
27 #include <utils/linked_list.h>
28 #include <plugins/plugin.h>
29
30 typedef struct private_plugin_loader_t private_plugin_loader_t;
31
32 /**
33 * private data of plugin_loader
34 */
35 struct private_plugin_loader_t {
36
37 /**
38 * public functions
39 */
40 plugin_loader_t public;
41
42 /**
43 * list of loaded plugins
44 */
45 linked_list_t *plugins;
46 };
47
48 /**
49 * load a single plugin
50 */
51 static plugin_t* load_plugin(private_plugin_loader_t *this,
52 char *path, char *name)
53 {
54 char file[PATH_MAX];
55 void *handle;
56 plugin_t *plugin;
57 plugin_constructor_t constructor;
58
59 snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path, name);
60
61 handle = dlopen(file, RTLD_LAZY);
62 if (handle == NULL)
63 {
64 DBG1("loading plugin '%s' failed: %s", name, dlerror());
65 return NULL;
66 }
67 constructor = dlsym(handle, "plugin_create");
68 if (constructor == NULL)
69 {
70 DBG1("loading plugin '%s' failed: no plugin_create() function", name);
71 dlclose(handle);
72 return NULL;
73 }
74 plugin = constructor();
75 if (plugin == NULL)
76 {
77 DBG1("loading plugin '%s' failed: plugin_create() returned NULL", name);
78 dlclose(handle);
79 return NULL;
80 }
81 DBG2("plugin '%s' loaded successfully", name);
82
83 /* we do not store or free dlopen() handles, leak_detective requires
84 * the modules to keep loaded until leak report */
85 return plugin;
86 }
87
88 /**
89 * Implementation of plugin_loader_t.load_plugins.
90 */
91 static int load(private_plugin_loader_t *this, char *path, char *list)
92 {
93 plugin_t *plugin;
94 char *pos;
95 int count = 0;
96
97 list = strdupa(list);
98 while (TRUE)
99 {
100 /* eat any whitespace in front */
101 while (*list == ' ')
102 {
103 list++;
104 }
105 /* have we reached the end of the list? */
106 if (!*list)
107 {
108 break;
109 }
110 pos = strchr(list, ' ');
111 if (pos)
112 {
113 *pos++ = '\0';
114 }
115 DBG1("loaded plugin: '%s'", list);
116 plugin = load_plugin(this, path, list);
117 if (plugin)
118 { /* insert in front to destroy them in reverse order */
119 this->plugins->insert_last(this->plugins, plugin);
120 count++;
121 }
122 if (pos)
123 {
124 list = pos;
125 }
126 else
127 {
128 break;
129 }
130 }
131 return count;
132 }
133
134 /**
135 * Implementation of plugin_loader_t.unload
136 */
137 static void unload(private_plugin_loader_t *this)
138 {
139 plugin_t *plugin;
140
141 while (this->plugins->remove_first(this->plugins,
142 (void**)&plugin) == SUCCESS)
143 {
144 plugin->destroy(plugin);
145 }
146 }
147
148 /**
149 * Implementation of plugin_loader_t.destroy
150 */
151 static void destroy(private_plugin_loader_t *this)
152 {
153 this->plugins->destroy_offset(this->plugins, offsetof(plugin_t, destroy));
154 free(this);
155 }
156
157 /*
158 * see header file
159 */
160 plugin_loader_t *plugin_loader_create()
161 {
162 private_plugin_loader_t *this = malloc_thing(private_plugin_loader_t);
163
164 this->public.load = (int(*)(plugin_loader_t*, char *path, char *prefix))load;
165 this->public.unload = (void(*)(plugin_loader_t*))unload;
166 this->public.destroy = (void(*)(plugin_loader_t*))destroy;
167
168 this->plugins = linked_list_create();
169
170 return &this->public;
171 }
172