/[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 1235 - (show annotations) (download) (as text)
Fri Dec 4 11:35:24 2009 UTC (12 years, 9 months ago) by aramv
File MIME type: text/x-chdr
File size: 11522 byte(s)
Moved around control logic of the parser to stop and report errors if they are encountered
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 plugin->handle = dlopen(abs_plugin_path, RTLD_NOW);
139
140 if(!plugin->handle){
141 eef_log(LOG_ERR, "Failed to acquire handle on plugin: %s\n", abs_plugin_path);
142 eef_log(LOG_ERR, "%s\n", dlerror());
143 return EES_FAILURE;
144 }
145
146 eef_log(LOG_DEBUG,"Linking plugin: %s\n", abs_plugin_path);
147
148 plugin->procs[INITPROC] = NULL;
149 plugin->procs[RUNPROC] = NULL;
150 plugin->procs[TERMPROC] = NULL;
151
152 /* link function pointers */
153 plugin->procs[INITPROC] = get_procsymbol(plugin->handle, "plugin_initialize");
154 if(plugin->procs[INITPROC] == NULL){
155 eef_log(LOG_ERR,"ees.mod-PluginInit(): plugin %s not compliant\n", plugin->name);
156 return EES_FAILURE;
157 }
158
159 plugin->procs[RUNPROC] = get_procsymbol(plugin->handle, "plugin_run");
160 if(plugin->procs[RUNPROC] == NULL){
161 eef_log(LOG_ERR, "ees.runPlugin\n");
162 return EES_FAILURE;
163 }
164
165 plugin->procs[TERMPROC] = get_procsymbol(plugin->handle, "plugin_terminate");
166 if(plugin->procs[TERMPROC] == NULL){
167 eef_log(LOG_ERR, "ees.termPlugin\n");
168 return EES_FAILURE;
169 }
170
171 set_running_plugin(plugin);
172 eef_log(LOG_INFO, "Initializing plugin %s\n", plugin->name);
173 init_fnc_ptr = plugin->procs[INITPROC];
174
175 /* call function pointer */
176 if(init_fnc_ptr(plugin->init_argc, plugin->init_argv) == EES_PL_SUCCESS){
177 return EES_SUCCESS;
178 } else {
179 eef_log(LOG_ERR, "Failed to initialize plugin %s\n", abs_plugin_path);
180 }
181
182 bzero(abs_plugin_path, strlen(abs_plugin_path) + 1);
183
184 return EES_FAILURE;
185 }
186
187 /* TODO fix */
188 /* Runs all the plugins
189 * Returns EES_SUCCESS if a plugin branch executed successfully. Returns EES_FAILURE if all plugin branches were exhausted unsuccessfully */
190 EES_RC run_plugins(policy_t* policy){
191 rule_t* temp_rule;
192 EES_RC retval = EES_FAILURE;
193 /* iterate policies */
194 while(policy && retval == EES_FAILURE){
195 /* evaluate rules */
196 temp_rule = policy->rules;
197 while(temp_rule){
198 eef_log(LOG_DEBUG, "Evaluating rule: %s\n", temp_rule->state);
199 if(temp_rule->plugin){
200 eef_log(LOG_DEBUG, "Running plugin: %s\n", temp_rule->plugin->name);
201 if(run_plugin(temp_rule->plugin) == EES_PL_SUCCESS){
202 if(temp_rule->true_branch){
203 eef_log(LOG_DEBUG, "Progressing to true branch %s\n", temp_rule->true_branch->state);
204 temp_rule = temp_rule->true_branch;
205 continue;
206 } else {
207 eef_log(LOG_DEBUG, "Executed policy %s successfully\n", policy->name);
208 eef_log(LOG_DEBUG, "Ended in rule %s\n", temp_rule->state);
209 /* all rules were exhausted and a successful state was reached */
210 retval = EES_SUCCESS;
211 break;
212 }
213 } else {
214 if(temp_rule->false_branch){
215 eef_log(LOG_DEBUG, "Progressing to false branch %s\n", temp_rule->false_branch->state);
216 temp_rule = temp_rule->false_branch;
217 continue;
218 } else {
219 /* all rules were exhausted and no successful state was reached */
220 retval = EES_FAILURE;
221 break;
222 }
223 }
224 } else {
225 /* plugin not linked to current rule - This should never happen */
226 eef_log(LOG_WARNING, "Rule %s at line %i is not linked to a plugin!\n", temp_rule->state, temp_rule->lineno);
227 return EES_FAILURE;
228 }
229 }
230 policy = policy->next;
231 }
232
233 return retval;
234 }
235
236 /** Calls the plugin's run method
237 */
238 EES_PL_RC run_plugin(eef_plugindl_t* plugin){
239 run_fnc_ptr = plugin->procs[RUNPROC];
240 eef_log(LOG_DEBUG, "Run method for %s linked at %p\n", plugin->name, run_fnc_ptr);
241 eef_log(LOG_INFO, "Running plugin %s\n", plugin->name);
242 set_running_plugin(plugin);
243 run_fnc_ptr();
244 return EES_SUCCESS;
245 }
246
247 /* run the plugin by name */
248 EES_PL_RC run_plugin_by_name(char* plugin_name){
249 eef_plugindl_t * current_plugin;
250 if((current_plugin = get_plugin(plugin_name))){
251 if((run_fnc_ptr = current_plugin->procs[RUNPROC])){
252 eef_log(LOG_DEBUG, "Run method for %s linked at %p\n", plugin_name, run_fnc_ptr);
253 eef_log(LOG_INFO, "Running plugin %s\n", plugin_name);
254 set_running_plugin(current_plugin);
255 run_fnc_ptr();
256 return EES_SUCCESS;
257 }
258 }
259 return EES_FAILURE;
260 }
261
262 /* Terminates all the plugins
263 * Returns EES_SUCCESS if all plugins terminated successfully.*/
264 EES_RC term_plugins(void){
265 eef_plugindl_t *node = plugin_list;
266 EES_RC retval = EES_SUCCESS;
267 while(node != NULL){
268 if(term_plugin(node->name) == EES_PL_FAILURE){
269 retval = EES_FAILURE;
270 }
271 node = node->next;
272 }
273 return retval;
274 }
275
276 /** Calls the plugin's term method
277 */
278 EES_PL_RC term_plugin(char* plugin_name){
279 eef_plugindl_t * current_plugin;
280 EES_RC retval = EES_SUCCESS;
281 if((current_plugin = get_plugin(plugin_name))){
282 if((term_fnc_ptr = current_plugin->procs[TERMPROC])){
283 eef_log(LOG_DEBUG, "Term method for %s linked at %p\n", plugin_name, term_fnc_ptr);
284 eef_log(LOG_INFO, "Terminating plugin %s\n", plugin_name);
285 set_running_plugin(current_plugin);
286 if(term_fnc_ptr() != EES_SUCCESS){
287 retval = EES_FAILURE;
288 }
289 }
290 }
291 return retval;
292 }
293
294 /** Stops the plugin manager, calling clean_plugin_list
295 */
296 EES_RC stop_plugin_manager(){
297 /*EES_RC retval = EES_SUCCESS;*/
298 if((term_plugins() == EES_SUCCESS) && (clean_plugin_list(plugin_list) == EES_SUCCESS)){
299 return EES_SUCCESS;
300 }
301 return EES_FAILURE;
302 }
303
304 /** Cleans the list of plugins, unlinking all the dlopened modules and freeing the structs
305 * \post The plugin list is empty
306 */
307 EES_RC clean_plugin_list(eef_plugindl_t * list){
308 eef_plugindl_t * plugin_entry=NULL;
309 eef_plugindl_t * plugin_next=NULL;
310 EES_RC retval = EES_SUCCESS;
311 int i;
312 plugin_entry=list;
313
314 /* iterate plugin_list */
315 while(plugin_entry!=NULL){
316 if(plugin_entry->handle != NULL){
317 /* Valgrind can't trace modules past their dlclose-ing. See: http://valgrind.org/docs/manual/faq.html#faq.unhelpful */
318 if(!getenv("VALGRIND")){
319 if((dlclose(plugin_entry->handle))){
320 eef_log(0, "dlclose error %s while cleaning up plugin list\n", dlerror());
321 retval = EES_FAILURE;
322 }
323 } else {
324 eef_log(LOG_DEBUG, "Running in valgrind, not dlclose'ing plugins\n");
325 }
326 }
327
328 /* free argv array */
329 for(i = 0; i < plugin_entry->init_argc; i++){
330 free(plugin_entry->init_argv[i]);
331 }
332
333 /* free current struct and move to next plugin */
334 plugin_next = plugin_entry->next;
335 free(plugin_entry);
336 plugin_entry = plugin_next;
337 }
338 return retval;
339 }
340
341
342 /** Prints the information from the plugin struct to the eef_log function with a specified debug level
343 */
344 EES_RC print_eef_plugin(int debug_lvl, eef_plugindl_t *plugin){
345 int i = 0;
346 /*eef_log(debug_lvl, "plugin name : %s\n", plugin->pluginname);*/
347 /*eef_log(debug_lvl, "plugin argc : %i\n", plugin->init_argc);*/
348 for(i = 1; i < plugin->init_argc; i++){
349 eef_log(debug_lvl, "plugin %s: argv[%i] : %s\n", plugin->init_argv[0] , i, plugin->init_argv[i]);
350 }
351 return EES_SUCCESS;
352 }
353
354 /** Internal method to keep track of which plugin is currently executing (used by AOS to determine ownership of data)
355 */
356 eef_plugindl_t * get_running_plugin(){
357 return _running_plugin;
358 }
359
360 /** Internal method to keep track of which plugin is currently executing
361 */
362 void set_running_plugin(eef_plugindl_t * plugin){
363 _running_plugin = plugin;
364 }
365

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