/[pdpsoft]/trunk/grid-mw-security/ees/src/plugin_manager/plugin_manager.c
ViewVC logotype

Contents of /trunk/grid-mw-security/ees/src/plugin_manager/plugin_manager.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1352 - (show annotations) (download) (as text)
Fri Jan 8 17:32:05 2010 UTC (12 years ago) by aramv
File MIME type: text/x-chdr
File size: 11521 byte(s)
Hunted memleaks in the new AOS - making progress slowly
1 #include "plugin_manager.h"
2 #include "_plugin_manager.h"
3
4 /** Starts the plugin manager (only initializes values to NULL)
5 */
6 EES_RC start_plugin_manager(){
7 plugin_list = NULL;
8 _running_plugin = NULL;
9 return EES_SUCCESS;
10 }
11
12 /** Prepares the supplied plugin by name, initializes the struct with these values
13 * \post the plugin node is ready to be passed to the initialize_plugin function
14 */
15 eef_plugindl_t * create_plugin_struct(int argc, char** argv){
16 eef_plugindl_t * current_plugin = NULL;
17 int i = 0;
18
19 /* current plugin struct */
20 if((current_plugin = calloc(1,sizeof(eef_plugindl_t)))){
21
22 strncpy(current_plugin->name, argv[0], FILENAME_MAX);
23 current_plugin->init_argc = argc;
24 for(i = 0; i < argc; i++){
25 current_plugin->init_argv[i] = (char*) strdup(argv[i]);
26 }
27 current_plugin->next = NULL;
28
29 /* cleanup */
30 for(i = 0; i < argc; i++){
31 free(argv[i]);
32 }
33 free(argv);
34
35 /* print information */
36 /*print_eef_plugin(LOG_DEBUG, current_plugin);*/
37
38 /* return plugin struct */
39 return current_plugin;
40 }
41 return NULL;
42 }
43
44 /** Calls create_plugin_struct() to create a plugin struct and adds it to the plugin_list
45 */
46 EES_RC add_plugin_struct(int argc, char* argv[]){
47 eef_plugindl_t *last_plugin = NULL, *current_plugin = NULL;
48 /* create_plugin_struct returns NULL if plugin failed to load. */
49 if((current_plugin = create_plugin_struct(argc, argv)) != NULL){
50 /* append plugin to the end of the list */
51 if(plugin_list == NULL){
52 plugin_list = current_plugin;
53 } else {
54 last_plugin = plugin_list;
55 /* TODO don't iterate list */
56 while(last_plugin->next != NULL){
57 last_plugin = last_plugin->next;
58 }
59 last_plugin->next = current_plugin;
60 }
61 /*print_eef_plugin(LOG_INFO, current_plugin);*/
62 return EES_SUCCESS;
63 }
64 return EES_FAILURE;
65 }
66
67 /** Wrapper for dlsym with error logging. Adapted from lcmaps_pluginmanager.c get_procsymbol
68 */
69 eef_proc_t get_procsymbol(void* handle, char* symname){
70 eef_proc_t symhandle;
71 char* errstring;
72
73 /* dlsym returns void pointer (data pointer) whereas we need to cast to a function pointer.
74 This is a known problem. See: http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html#tag_03_112_08
75 Although gcc will produce a warning this seems to work on most platforms
76 */
77 symhandle = dlsym(handle,symname);
78
79 if((errstring = dlerror()) != NULL){
80 eef_log(0, "ees.get_procsymbol(): dlsym error %s\n", errstring);
81 return NULL;
82 }
83
84 return symhandle;
85 }
86
87 /** Returns a plugin from the list by name, or NULL if not found
88 */
89 eef_plugindl_t* get_plugin(char* plugin_name){
90 eef_plugindl_t * current_plugin = plugin_list;
91 /* iterate plugin_list until plugin is found */
92 while(current_plugin != NULL){
93 if(strcmp(current_plugin->name, plugin_name) == 0){
94 return current_plugin;
95 }
96 current_plugin = current_plugin->next;
97 }
98 return NULL;
99 }
100
101 /* Initializes all the plugins
102 * Returns EES_SUCCESS or EES_FAILURE if a plugin failed to load.*/
103 EES_RC initialize_plugins(){
104 eef_plugindl_t* node = plugin_list;
105 local_module_dir = get_modules_path();
106 eef_log(LOG_DEBUG, "Using modules path: %s\n", local_module_dir);
107 while(node != NULL){
108 if(initialize_plugin(node) == EES_FAILURE){
109 return EES_FAILURE;
110 }
111 node = node->next;
112 }
113 return EES_SUCCESS;
114 }
115
116 /** Initializes the supplied plugin node, which already holds the plugin name and arguments
117 * \post the plugin node is initialized and its functions are linked and accessible
118 */
119 EES_RC initialize_plugin(eef_plugindl_t* plugin){
120 size_t max_plugin_name = FILENAME_MAX - strlen(local_module_dir);
121
122 if(strlen(local_module_dir) >= FILENAME_MAX){
123 return EES_FAILURE;
124 }
125 memset(abs_plugin_path, 0, FILENAME_MAX);
126
127 /*TODO make safer */
128 if(!(strncat(abs_plugin_path, local_module_dir, strlen(local_module_dir)) && \
129 strncat(abs_plugin_path, plugin->init_argv[0], max_plugin_name)
130 /*&& strcat(abs_plugin_path, ".mod")*/
131 )){
132 return EES_FAILURE;
133 }
134
135 eef_log(LOG_DEBUG, "Loading plugin %s\n", abs_plugin_path);
136
137 /* load plugin handle */
138 if(!(plugin->handle = dlopen(abs_plugin_path, RTLD_NOW))){
139 eef_log(LOG_ERR, "Failed to acquire handle on plugin: %s\n", abs_plugin_path);
140 eef_log(LOG_ERR, "%s\n", dlerror());
141 return EES_FAILURE;
142 }
143
144 eef_log(LOG_DEBUG,"Linking plugin: %s\n", abs_plugin_path);
145
146 plugin->procs[INITPROC] = NULL;
147 plugin->procs[RUNPROC] = NULL;
148 plugin->procs[TERMPROC] = NULL;
149
150 /* link function pointers */
151 plugin->procs[INITPROC] = get_procsymbol(plugin->handle, "plugin_initialize");
152 if(plugin->procs[INITPROC] == NULL){
153 eef_log(LOG_ERR,"ees.mod-PluginInit(): plugin %s not compliant\n", plugin->name);
154 return EES_FAILURE;
155 }
156
157 plugin->procs[RUNPROC] = get_procsymbol(plugin->handle, "plugin_run");
158 if(plugin->procs[RUNPROC] == NULL){
159 eef_log(LOG_ERR, "ees.runPlugin\n");
160 return EES_FAILURE;
161 }
162
163 plugin->procs[TERMPROC] = get_procsymbol(plugin->handle, "plugin_terminate");
164 if(plugin->procs[TERMPROC] == NULL){
165 eef_log(LOG_ERR, "ees.termPlugin\n");
166 return EES_FAILURE;
167 }
168
169 set_running_plugin(plugin);
170 eef_log(LOG_INFO, "Initializing plugin %s\n", plugin->name);
171 init_fnc_ptr = plugin->procs[INITPROC];
172
173 /* call function pointer */
174 if(init_fnc_ptr(plugin->init_argc, plugin->init_argv) == EES_PL_SUCCESS){
175 return EES_SUCCESS;
176 } else {
177 eef_log(LOG_ERR, "Failed to initialize plugin %s\n", abs_plugin_path);
178 }
179
180 bzero(abs_plugin_path, strlen(abs_plugin_path) + 1);
181
182 return EES_FAILURE;
183 }
184
185 /* TODO fix */
186 /* Runs all the plugins
187 * Returns EES_SUCCESS if a plugin branch executed successfully. Returns EES_FAILURE if all plugin branches were exhausted unsuccessfully */
188 EES_RC run_plugins(policy_t* policy){
189 rule_t* temp_rule;
190 EES_RC retval = EES_FAILURE;
191 /* iterate policies */
192 while(policy && retval == EES_FAILURE){
193 /* evaluate rules */
194 temp_rule = policy->rules;
195 while(temp_rule){
196 eef_log(LOG_DEBUG, "Evaluating rule: %s\n", temp_rule->state);
197 if(temp_rule->plugin){
198 eef_log(LOG_DEBUG, "Running plugin: %s\n", temp_rule->plugin->name);
199 if(run_plugin(temp_rule->plugin) == EES_PL_SUCCESS){
200 if(temp_rule->true_branch){
201 eef_log(LOG_DEBUG, "Progressing to true branch %s\n", temp_rule->true_branch->state);
202 temp_rule = temp_rule->true_branch;
203 continue;
204 } else {
205 eef_log(LOG_DEBUG, "Executed policy %s successfully\n", policy->name);
206 eef_log(LOG_DEBUG, "Ended in rule %s\n", temp_rule->state);
207 /* all rules were exhausted and a successful state was reached */
208 retval = EES_SUCCESS;
209 break;
210 }
211 } else {
212 if(temp_rule->false_branch){
213 eef_log(LOG_DEBUG, "Progressing to false branch %s\n", temp_rule->false_branch->state);
214 temp_rule = temp_rule->false_branch;
215 continue;
216 } else {
217 /* all rules were exhausted and no successful state was reached */
218 retval = EES_FAILURE;
219 break;
220 }
221 }
222 } else {
223 /* plugin not linked to current rule - This should never happen */
224 eef_log(LOG_WARNING, "Rule %s at line %i is not linked to a plugin!\n", temp_rule->state, temp_rule->lineno);
225 return EES_FAILURE;
226 }
227 }
228 policy = policy->next;
229 }
230
231 return retval;
232 }
233
234 /** Calls the plugin's run method
235 */
236 EES_PL_RC run_plugin(eef_plugindl_t* plugin){
237 run_fnc_ptr = plugin->procs[RUNPROC];
238 eef_log(LOG_DEBUG, "Run method for %s linked at %p\n", plugin->name, run_fnc_ptr);
239 eef_log(LOG_INFO, "Running plugin %s\n", plugin->name);
240 set_running_plugin(plugin);
241 run_fnc_ptr();
242 return EES_SUCCESS;
243 }
244
245 /* run the plugin by name */
246 EES_PL_RC run_plugin_by_name(char* plugin_name){
247 eef_plugindl_t * current_plugin;
248 if((current_plugin = get_plugin(plugin_name))){
249 if((run_fnc_ptr = current_plugin->procs[RUNPROC])){
250 eef_log(LOG_DEBUG, "Run method for %s linked at %p\n", plugin_name, run_fnc_ptr);
251 eef_log(LOG_INFO, "Running plugin %s\n", plugin_name);
252 set_running_plugin(current_plugin);
253 run_fnc_ptr();
254 return EES_SUCCESS;
255 }
256 }
257 return EES_FAILURE;
258 }
259
260 /* Terminates all the plugins
261 * Returns EES_SUCCESS if all plugins terminated successfully.*/
262 EES_RC term_plugins(void){
263 eef_plugindl_t *node = plugin_list;
264 EES_RC retval = EES_SUCCESS;
265 while(node != NULL){
266 if(term_plugin(node->name) == EES_PL_FAILURE){
267 retval = EES_FAILURE;
268 }
269 node = node->next;
270 }
271 return retval;
272 }
273
274 /** Calls the plugin's term method
275 */
276 EES_PL_RC term_plugin(char* plugin_name){
277 eef_plugindl_t * current_plugin;
278 EES_RC retval = EES_SUCCESS;
279 if((current_plugin = get_plugin(plugin_name))){
280 if((term_fnc_ptr = current_plugin->procs[TERMPROC])){
281 eef_log(LOG_DEBUG, "Term method for %s linked at %p\n", plugin_name, term_fnc_ptr);
282 eef_log(LOG_INFO, "Terminating plugin %s\n", plugin_name);
283 set_running_plugin(current_plugin);
284 if(term_fnc_ptr() != EES_SUCCESS){
285 retval = EES_FAILURE;
286 }
287 }
288 }
289 return retval;
290 }
291
292 /** Stops the plugin manager, calling clean_plugin_list
293 */
294 EES_RC stop_plugin_manager(){
295 /*EES_RC retval = EES_SUCCESS;*/
296 if((term_plugins() == EES_SUCCESS) && (clean_plugin_list(plugin_list) == EES_SUCCESS)){
297 return EES_SUCCESS;
298 }
299 return EES_FAILURE;
300 }
301
302 /** Cleans the list of plugins, unlinking all the dlopened modules and freeing the structs
303 * \post The plugin list is empty
304 */
305 EES_RC clean_plugin_list(eef_plugindl_t * list){
306 eef_plugindl_t * plugin_entry = list;
307 eef_plugindl_t * plugin_next = NULL;
308 EES_RC retval = EES_SUCCESS;
309 int i;
310
311 /* iterate plugin_list */
312 while(plugin_entry!=NULL){
313 if(plugin_entry->handle != NULL){
314 /* Valgrind can't trace modules past their dlclose-ing. See: http://valgrind.org/docs/manual/faq.html#faq.unhelpful */
315 if(!getenv("VALGRIND")){
316 if((dlclose(plugin_entry->handle))){
317 eef_log(LOG_ERR, "dlclose error %s while cleaning up plugin list\n", dlerror());
318 retval = EES_FAILURE;
319 }
320 } else {
321 eef_log(LOG_DEBUG, "Running in valgrind, not dlclose'ing plugins\n");
322 }
323 }
324
325 /* free argv array */
326 for(i = 0; i < plugin_entry->init_argc; i++){
327 free(plugin_entry->init_argv[i]);
328 }
329
330 /* free current struct and move to next plugin */
331 plugin_next = plugin_entry->next;
332 free(plugin_entry);
333 plugin_entry = plugin_next;
334 }
335 return retval;
336 }
337
338
339 /** Prints the information from the plugin struct to the eef_log function with a specified debug level
340 */
341 EES_RC print_eef_plugin(int debug_lvl, eef_plugindl_t *plugin){
342 int i = 0;
343 /*eef_log(debug_lvl, "plugin name : %s\n", plugin->pluginname);*/
344 /*eef_log(debug_lvl, "plugin argc : %i\n", plugin->init_argc);*/
345 for(i = 1; i < plugin->init_argc; i++){
346 eef_log(debug_lvl, "plugin %s: argv[%i] : %s\n", plugin->init_argv[0] , i, plugin->init_argv[i]);
347 }
348 return EES_SUCCESS;
349 }
350
351 /** Internal method to keep track of which plugin is currently executing (used by AOS to determine ownership of data)
352 */
353 eef_plugindl_t * get_running_plugin(){
354 return _running_plugin;
355 }
356
357 /** Internal method to keep track of which plugin is currently executing
358 */
359 void set_running_plugin(eef_plugindl_t * plugin){
360 _running_plugin = plugin;
361 }
362

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28