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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1894 - (show annotations) (download) (as text)
Thu Aug 26 15:00:24 2010 UTC (11 years, 9 months ago) by aramv
File MIME type: text/x-chdr
File size: 28861 byte(s)
Fixed warnings and a bit of general cleanup
1 #include "pdl.h"
2 #include <stdlib.h>
3 #include "plugin_manager.h"
4 #include "eef_library.h"
5
6 /* Lex/Yacc stuff */
7 extern FILE * yyin;
8 extern unsigned int lineno;
9 extern int yyparse(void);
10 extern int yylex(void);
11
12 pdl_data_t config;
13
14 /* This function does everything parser related. After running yacc through wrap_yacc(), the created list is reduced to those in the array of named policies, of number_of_policies is greater than 0. The policies are checked for unreachable rules. After the parser has created a list of policies containing lists of rules, these rules are transformed to a tree by the link_dead_end_rules_in_policies() function. Finally, when a list of policies containing rules trees was created, the plug-ins are linked to each rule in the node. */
15 EES_RC start_pdl_parser(char *config_file, int number_of_policies, char* names_of_policies[]){
16 config.recursion_was_created = 0;
17 config.unknown_variable_was_referenced = 0;
18 config.starting_state_was_reused = 0;
19 config.parse_errors_detected = 0;
20
21 EEF_log(LOG_NOTICE, "Loading config file: %s\n", config_file);
22 if(wrap_yacc(config_file) == EES_SUCCESS){
23 /* after the config file was successfully parsed, the policies and path to plugins are accessible. We can try to set the global (EEF-wide) modules path if one was provided */
24 EEF_log(LOG_NOTICE, "Loaded config file: %s\n", config_file);
25
26 /* set the EEF modules path to the path found by the evaluation manager */
27 EEF_set_modules_path(get_pdl_path());
28
29 /* strip policies that are not explicitly passed in the names_of_policies array */
30 if(number_of_policies){
31 config.policies_list = reduce_policies(config.policies_list, number_of_policies, names_of_policies);
32 }
33
34 if(remove_unreachable_rules_in_policies(config.policies_list) == EES_SUCCESS){
35 if(config.policies_list){
36 link_dead_end_rules_in_policies(config.policies_list);
37 link_rules_to_plugins(config.policies_list);
38 }
39 EEF_log(LOG_INFO, "Your configuration file seems sane.\n");
40 print_policies(config.policies_list);
41
42 /* this is a callout to the plugin manager, which dlopen()'s the plugin, dlsym()'s the plugin's functions and calls the plugin's initialize function */
43 if(initialize_plugins() == EES_SUCCESS){
44 return EES_SUCCESS;
45 } else {
46 EEF_log(LOG_ERR, "Failed to initialize plug-ins from policy config file %s\n", config_file);
47 }
48 } else {
49 EEF_log(LOG_ERR, "The loaded configuration file defines unreachable rules. Please check your configuration file.");
50 }
51 } else {
52 if(config.recursion_was_created){
53 EEF_log(LOG_ERR, "The loaded configuration file defines recursive rules. Please check your configuration file.");
54 }
55 if(config.unknown_variable_was_referenced){
56 EEF_log(LOG_ERR, "The loaded configuration file references undefined variables. Please check your configuration file.");
57 }
58 if(config.starting_state_was_reused){
59 EEF_log(LOG_ERR, "The loaded configuration file reuses a starting state. Please check your configuration file.");
60 }
61 if(config.parse_errors_detected){
62 EEF_log(LOG_ERR, "The configuration was not parsed correctly. Please check your configuration file.");
63 }
64 }
65 return EES_FAILURE;
66 }
67
68
69 /*! Initializes the parsing of the configuration file. When parsing has completed successfully, the policy_list is available. This can be transformed to a tree using the link_dead_end_rules_in_policies() function. */
70 EES_RC wrap_yacc(const char* config_file){
71 config.config_file_s = config_file;
72 if((config.config_file_fp = fopen(config.config_file_s,"r")) != NULL){
73 yyin = config.config_file_fp;
74 yyparse();
75 if(!config.recursion_was_created && !config.unknown_variable_was_referenced && !config.starting_state_was_reused && !config.parse_errors_detected){
76 /* callout to the plugin manager */
77 if(add_plugin_structs() == EES_SUCCESS){
78 return EES_SUCCESS;
79 } else {
80 EEF_log(LOG_ERR, "Failed to load plug-ins from policy config file %s\n", config.config_file_s);
81 }
82 }
83 } else {
84 EEF_log(LOG_ERR, "Failed to open policy config file %s", config.config_file_s);
85 }
86 return EES_FAILURE;
87 }
88
89 policy_t* get_policies(){
90 return config.policies_list;
91 }
92
93 /*! sets the path to modules directory */
94 void set_pdl_path(record_t* path){
95 size_t path_size = 0;
96 size_t string_size = (sizeof(char) * (strlen(path->string)+2)); /* size of string + extra slash + null byte */
97 config.pdl_path = "";
98
99 /*struct stat sb;*/
100 /*if stat(MODUL*/
101
102 if(string_size < FILENAME_MAX){
103 path_size = string_size;
104 } else {
105 path_size = FILENAME_MAX;
106 }
107
108 if((config.pdl_path = calloc(1, path_size))){
109 strncpy(config.pdl_path, path->string, path_size);
110 strncat(config.pdl_path, "/", 1);
111 }
112
113 EEF_log(LOG_DEBUG, "Found a new modules path: %s\n", config.pdl_path);
114
115 free(path->string);
116 path->string = NULL;
117 free(path);
118 path = NULL;
119 }
120
121 /*! Handles a variable representing a plug-in; creates a structure containing its values and adds it to the list of var_t structs variables_list */
122 void add_variable(record_t* name, record_t* value){
123 EEF_log(LOG_DEBUG, "Added variable name: %s\n", name->string);
124 EEF_log(LOG_DEBUG, "Added variable value: %s\n", value->string);
125
126 /* allocate struct and populate fields */
127 if((config.current_variable = calloc(1,sizeof(var_t)))){
128 config.current_variable->name = strdup(name->string);
129 config.current_variable->value = strdup(value->string);
130 config.current_variable->lineno = name->lineno;
131 config.current_variable->next = NULL;
132 } else {
133 EEF_log(LOG_ERR, "Out of memory!");
134 }
135
136 /* append to the end of the list */
137 if(config.variables_list){
138 config.variables_list_last->next = config.current_variable;
139 } else {
140 config.variables_list = config.current_variable;
141 }
142 config.variables_list_last = config.current_variable;
143
144 /* clean up */
145 free(name->string);
146 name->string = NULL;
147 free(name);
148 name = NULL;
149 free(value->string);
150 value->string = NULL;
151 free(value);
152 value = NULL;
153 }
154
155 /* TODO I think this function is a bit of a kludge and could probably be rewritten to be more efficient and more legible - I think it might do too much, so extracting some functions might help */
156 /*! Appends a rule to the global rules_list, which is to be added to a policy when add_policy is called
157 Will return NULL and log an error when:
158 - adding the rule to the list will create a recursion in the tree of rules
159 - an unknown variable is referenced
160 */
161 rule_t* add_rule(record_t* state, record_t* true_branch, record_t* false_branch){
162 rule_t *new_rule = NULL, *new_false_branch = NULL, *new_true_branch = NULL, *recursive_rule = NULL;
163 var_t *temp_var = NULL;
164 char *unknown_var_format_string = "Unknown variable %s at line %i in config file %s";
165
166 if((new_rule = get_left_hand_rule(config.rules_list, state->string))){
167 EEF_log(LOG_WARNING, "State %s at line %i is already in use at line %i.\n", state->string, state->lineno, new_rule->lineno);
168 config.starting_state_was_reused = 1;
169 } else {
170 /*find variables for rule */
171 temp_var = get_variable_by_name(state->string);
172 if(temp_var == NULL){
173 /* Errorous state - variable referenced in rule not previously defined */
174 EEF_log(LOG_ERR, unknown_var_format_string, state->string, state->lineno, config.config_file_s);
175 config.unknown_variable_was_referenced = 1;
176 new_rule = clean_rules_tree(new_rule);
177 goto cleanup;
178 }
179 if(temp_var != NULL){
180 if((new_rule = calloc(1, sizeof(rule_t)))){
181 /* populate fields of current state */
182 new_rule->state = strdup(state->string);
183 new_rule->lineno = state->lineno;
184
185 /* populate fields of branches */
186 if(false_branch){
187 temp_var = get_variable_by_name(false_branch->string);
188 if(temp_var == NULL){
189 /* Errorous state - variable referenced in rule not previously defined */
190 EEF_log(LOG_ERR, unknown_var_format_string, false_branch->string, false_branch->lineno, config.config_file_s);
191 config.unknown_variable_was_referenced = 1;
192 new_rule = clean_rules_tree(new_rule);
193 goto cleanup;
194 } else {
195 if((new_false_branch = calloc(1, sizeof(rule_t)))){
196 new_false_branch->state = strdup(false_branch->string);
197 new_false_branch->lineno = false_branch->lineno;
198 new_rule->false_branch = new_false_branch;
199 }
200 }
201 }
202
203 if(true_branch){
204 temp_var = get_variable_by_name(true_branch->string);
205 if(temp_var == NULL){
206 /* Errorous state - variable referenced in rule not previously defined */
207 EEF_log(LOG_ERR, unknown_var_format_string, true_branch->string, true_branch->lineno, config.config_file_s);
208 config.unknown_variable_was_referenced = 1;
209 new_rule = clean_rules_tree(new_rule);
210 goto cleanup;
211 } else {
212 if((new_true_branch = calloc(1, sizeof(rule_t)))){
213 new_true_branch->state = strdup(true_branch->string);
214 new_true_branch->lineno = true_branch->lineno;
215 new_rule->true_branch = new_true_branch;
216 }
217 }
218 }
219
220 /* check for recursion */
221 if((recursive_rule = check_for_recursion(config.rules_list, new_rule))){
222 EEF_log(LOG_WARNING, "Rule %s at line %i leads to recursion into state %s", new_rule->state, new_rule->lineno, recursive_rule->state);
223 new_rule = clean_rules_tree(new_rule);
224 config.recursion_was_created = 1;
225 goto cleanup;
226 } else {
227 /* add new rule at the end of the rules list */
228 if(config.rules_list){
229 config.rules_list_last->next = new_rule;
230 } else {
231 config.rules_list = new_rule;
232 }
233 config.rules_list_last = new_rule;
234
235 EEF_log(LOG_DEBUG, "Added a new rule: %s\n", new_rule->state);
236 }
237
238 } else {
239 EEF_log(LOG_ERR, "Out of memory!");
240 }
241 }
242 }
243
244 cleanup:
245
246 /* clean up */
247 if(state != NULL){
248 free(state->string);
249 free(state);
250 }
251 if(true_branch != NULL){
252 free(true_branch->string);
253 free(true_branch);
254 }
255 if(false_branch != NULL){
256 free(false_branch->string);
257 free(false_branch);
258 }
259
260 return new_rule;
261 }
262
263 /* Tries to find a recursion in the list of rules by iterating through all the tree branches. When the same rule is encountered in the current list a recursion has been found */
264 rule_t* check_for_recursion(rule_t* rule_l, rule_t* rule_r){
265 rule_t* temp_rule = rule_l;
266
267 /* right hand rule leads to its own recursive state */
268 /* still need to find a way to reuse the code from the while loop to do this check */
269 if(rule_r){
270 if(rule_r->true_branch){
271 if(strcmp(rule_r->state, rule_r->true_branch->state) == 0){
272 return rule_r->true_branch;
273 }
274 }
275
276 if(rule_r->false_branch){
277 if(strcmp(rule_r->state, rule_r->false_branch->state) == 0){
278 return rule_r->false_branch;
279 }
280 }
281 }
282
283 /* iterate list of rules */
284 while(temp_rule){
285 if((temp_rule != NULL) && (rule_r != NULL)){
286 /* left hand and right hand state are equal */
287 if(strcmp(temp_rule->state, rule_r->state) == 0){
288 return rule_r;
289 }
290
291 /* start state and true branch of right hand rule are equal */
292 if(rule_r->true_branch){
293 if(strcmp(temp_rule->state, rule_r->true_branch->state) == 0){
294 return rule_r->true_branch;
295 }
296 }
297
298 /* start state and false branch of right hand side are equal */
299 if(rule_r->false_branch){
300 if(strcmp(temp_rule->state, rule_r->false_branch->state) == 0){
301 return rule_r->false_branch;
302 }
303 }
304 }
305
306 /* move to next rule */
307 temp_rule = temp_rule->next;
308 }
309 return NULL;
310 }
311
312 /* This function iterates the passed list of policies and removes unreachable rules from each policy */
313 EES_RC remove_unreachable_rules_in_policies(policy_t* policies){
314 policy_t *temp_policy = policies;
315 EES_RC retval = EES_SUCCESS;
316 while(temp_policy){
317 temp_policy->rules = remove_unreachable_rules(temp_policy->rules, &retval);
318 temp_policy = temp_policy->next;
319 }
320 return retval;
321 }
322
323 /* This function iterates the passed list of rules and removes those rules that, while they exist on the left-hand side, are never referenced on the right-hand side of a rule in the list */
324 rule_t* remove_unreachable_rules(rule_t* rules, EES_RC *retval){
325 rule_t *temp_rule = NULL, *next_rule = NULL, *previous_rule = rules;
326 if(rules){
327 temp_rule = rules->next;
328 while(temp_rule){
329 next_rule = temp_rule->next;
330
331 if(!(get_right_hand_rule(rules, temp_rule->state))){
332 EEF_log(LOG_WARNING, "Removing unreachable rule %s at line %i\n", temp_rule->state, temp_rule->lineno);
333 clean_rules_tree(temp_rule);
334 previous_rule->next = next_rule;
335 temp_rule = previous_rule;
336 *retval = EES_FAILURE;
337 }
338 previous_rule = temp_rule;
339 temp_rule = next_rule;
340 }
341 }
342 return rules;
343 }
344
345 void link_dead_end_rules_in_policies(policy_t* policy){
346 policy_t* temp_policy = policy;
347 while(temp_policy){
348 link_dead_end_rules(temp_policy, temp_policy->rules);
349 temp_policy = temp_policy->next;
350 }
351 }
352
353 void link_dead_end_rules(policy_t* policy, rule_t* rule){
354 rule_t *temp_rule = rule, *true_rule, *false_rule;
355 while(temp_rule){
356 if(temp_rule->true_branch){
357 if((true_rule = get_left_hand_rule(policy->rules, temp_rule->true_branch->state))){
358 EEF_log(LOG_DEBUG, "Overwriting rule %s with %s\n", temp_rule->true_branch->state, true_rule->state);
359 clean_rules_tree(temp_rule->true_branch);
360 temp_rule->true_branch = true_rule;
361 }
362 }
363 if(temp_rule->false_branch){
364 if((false_rule = get_left_hand_rule(policy->rules, temp_rule->false_branch->state))){
365 EEF_log(LOG_DEBUG, "Overwriting rule %s with %s\n", temp_rule->false_branch->state, false_rule->state);
366 clean_rules_tree(temp_rule->false_branch);
367 temp_rule->false_branch = false_rule;
368 }
369 }
370 temp_rule = temp_rule->next;
371 }
372 policy->rules_list_transformed_to_tree = 1;
373 }
374
375 /*! Tries to find specified state in the rules_list */
376 rule_t* get_left_hand_rule(rule_t* temp_rule, const char* name){
377 if(!temp_rule || !name){
378 return NULL;
379 }
380
381 /* iterate while the rule isn't associated with the given state */
382 while(temp_rule){
383 if(!strcmp(name, temp_rule->state)){
384 return temp_rule;
385 }
386 temp_rule = temp_rule->next;
387 }
388 return NULL;
389 }
390
391 /*! Tries to find specified state in the rules_list */
392 rule_t* get_right_hand_rule(rule_t* temp_rule, const char* name){
393 if(!temp_rule || !name){
394 return NULL;
395 } else {
396 /* iterate while the rule isn't associated with the given state */
397 if(temp_rule->true_branch){
398 if(strcmp(name, temp_rule->true_branch->state) == 0){
399 return temp_rule->true_branch;
400 }
401 }
402 if(temp_rule->false_branch){
403 if(strcmp(name, temp_rule->false_branch->state) == 0){
404 return temp_rule->false_branch;
405 }
406 }
407 }
408 return NULL;
409 }
410
411 /*! Adds a new policy_t structure to the policies_list which will hold the current rules_list. rules_list is nulled after creating a policy so a new list can be created for the next policy */
412 void add_policy(record_t* policy, rule_t* top_rule){
413 policy_t* new_policy = NULL;
414 /*eef_log(LOG_DEBUG, "Found a new policy: %s\n", policy->string);*/
415
416 if((new_policy = calloc(1, sizeof(policy_t)))){
417 new_policy->name = strdup(policy->string);
418 new_policy->lineno = policy->lineno;
419 new_policy->rules = top_rule;
420 new_policy->rules_list_transformed_to_tree = 0;
421 new_policy->next = NULL;
422 }
423
424 /* append to the end of the list */
425 if(config.policies_list){
426 config.policies_list_last->next = new_policy;
427 } else {
428 config.policies_list = new_policy;
429 }
430 config.policies_list_last = new_policy;
431
432 /* start a new rules list */
433 config.rules_list = NULL;
434
435 free(policy->string);
436 policy->string = NULL;
437 free(policy);
438 policy = NULL;
439 }
440
441 /* prints the list of policies */
442 void print_policies(policy_t* policies){
443 policy_t* temp_policy = policies;
444 while(temp_policy){
445 EEF_log(LOG_DEBUG, "Policy: %s\n", temp_policy->name);
446 print_rules(temp_policy, temp_policy->rules);
447 temp_policy = temp_policy->next;
448 }
449 return;
450 }
451
452
453 /* prints the list of rules */
454 void print_rules(policy_t* policy, rule_t* rule){
455 if(rule){
456 EEF_log(LOG_DEBUG, " | Rule %s\n", rule->state);
457 EEF_log(LOG_DEBUG, " -------------------------\n");
458 if(rule->true_branch){
459 print_rules(policy, get_left_hand_rule(policy->rules, rule->true_branch->state));
460 }
461 if(rule->false_branch){
462 print_rules(policy, get_left_hand_rule(policy->rules, rule->false_branch->state));
463 }
464 }
465 return;
466 }
467
468 /* tries to link all policy rules to a plugin in the plugin manager */
469 EES_RC link_rules_to_plugins(policy_t* policies){
470 policy_t *temp_policy = policies;
471
472 while(temp_policy){
473 link_rule_to_plugin(temp_policy, temp_policy->rules);
474 temp_policy = temp_policy->next;
475 }
476 return EES_SUCCESS;
477 }
478
479 void link_rule_to_plugin(policy_t *policy, rule_t *rule){
480 var_t *temp_var = NULL;
481 char** argv;
482 int argc;
483
484 eef_plugindl_t *temp_plugin = NULL;
485 if(rule){
486 if(!rule->plugin){
487 temp_var = get_variable_by_name(rule->state);
488 if(temp_var){
489 argv = _var_to_argv(temp_var->value, &argc);
490
491 temp_plugin = get_plugin(temp_var->name);
492 if(temp_plugin){
493 rule->plugin = temp_plugin;
494 } else {
495 EEF_log(LOG_WARNING, "Unknown plugin in variable %s\n", temp_var->value);
496 }
497 free_args(argc, argv);
498 }
499 } else {
500 EEF_log(LOG_DEBUG, "Plugin already linked?\n");
501 }
502 link_rule_to_plugin(policy, rule->true_branch);
503 link_rule_to_plugin(policy, rule->false_branch);
504 }
505 return;
506 }
507
508 /* iterates the policies and removes those that are not explicitly named in the passed array of strings */
509 policy_t* reduce_policies(policy_t* policies, int number_of_policies, char* names_of_policies[]){
510 int i, policy_should_be_removed;
511 policy_t *temp_policy = policies, *next_policy = NULL;
512
513 while(temp_policy){
514 policy_should_be_removed = 1;
515 EEF_log(LOG_DEBUG, "Checking policy: %s\n", (temp_policy)->name);
516 for(i = 0; i < number_of_policies; i++){
517 if(strcmp(temp_policy->name, names_of_policies[i]) == 0){
518 /* if the policy is in the named list, we can continue to the next plugin */
519 EEF_log(LOG_DEBUG, "Allowed policy: %s\n", names_of_policies[i]);
520 policy_should_be_removed = 0;
521 break;
522 }
523 }
524
525 next_policy = temp_policy->next;
526
527 if(policy_should_be_removed){
528 EEF_log(LOG_DEBUG, "Removing not-allowed policy: %s\n", temp_policy->name);
529 policies = remove_policy_by_name(policies, temp_policy->name);
530 }
531 temp_policy = next_policy;
532 }
533
534 return policies;
535 }
536
537 /*! concatenates two strings */
538 record_t* concat_strings(record_t* r1, record_t* r2){
539 record_t* new_record;
540 /*eef_log(LOG_DEBUG, "Concating: %s with %s\n", r1->string, r2->string);*/
541 if((new_record = malloc(sizeof(record_t)))){
542 if((new_record->string =
543 calloc(1, sizeof(char)*(strlen(r1->string) + strlen(r2->string)+1)))){
544 strncat(new_record->string, r1->string, strlen(r1->string));
545 strncat(new_record->string, r2->string, strlen(r2->string));
546 free(r1->string);
547 free(r1);
548 free(r2->string);
549 free(r2);
550 return new_record;
551 }
552 }
553 return NULL;
554 }
555
556 /*! concatenates two strings with a space in between */
557 record_t* concat_strings_with_space(record_t *r1, record_t* r2){
558 record_t *r;
559 /*eef_log(LOG_DEBUG, "Concating: %s with %s with spaces\n", r1->string, r2->string);*/
560 if((r = malloc(sizeof(record_t)))){
561 r->string = calloc(1,(sizeof(char)*(strlen(r1->string)+strlen(r2->string)+2)));
562 strncat(r->string, r1->string, strlen(r1->string));
563 strncat(r->string, " ", 1);
564 strncat(r->string, r2->string, strlen(r2->string));
565 free(r1->string);
566 free(r1);
567 free(r2->string);
568 free(r2);
569 return r;
570 }
571 return NULL;
572 }
573
574 /*! logs errors encountered during parsing */
575 int yyerror(char* string){
576 config.parse_errors_detected = 1;
577 EEF_log(LOG_ERR, "Parse error: %s at line %i in config file %s", string, lineno, config.config_file_s);
578 return 0;
579 }
580
581 /*! get variable from list */
582 var_t* get_variable_by_name(char* name){
583 for(config.current_variable = config.variables_list; config.current_variable != NULL; config.current_variable = config.current_variable->next){
584 if(!strncmp(name, config.current_variable->name, strlen(config.current_variable->name))){
585 return config.current_variable;
586 }
587 }
588 return NULL;
589 }
590
591 /*! Removes a policy from the list of policies */
592 void remove_policy(record_t* policy){
593 policy_t *temp_policy = config.policies_list, *next_policy = NULL;
594 EEF_log(LOG_DEBUG, "Deleted policy: %s\n", policy->string);
595
596 while(temp_policy){
597 if(strcmp(temp_policy->name, policy->string) == 0){
598 /* target policy was found */
599 next_policy = temp_policy->next;
600
601 /* Clean policy fields */
602 if(temp_policy->rules_list_transformed_to_tree){
603 temp_policy->rules = clean_rules_tree(temp_policy->rules);
604 } else {
605 temp_policy->rules = clean_rules_list(temp_policy->rules);
606 }
607 free(temp_policy->name);
608 temp_policy->name = NULL;
609 free(temp_policy);
610 temp_policy = NULL;
611 }
612
613 /* Move to next policy */
614 temp_policy = next_policy;
615 }
616
617 free(policy->string);
618 free(policy);
619 return;
620 }
621
622 /*! Removes a policy from the list of policies */
623 policy_t* remove_policy_by_name(policy_t* policies, char* policy){
624 policy_t *temp_policy = NULL, *next_policy = NULL, *previous_policy = NULL;
625
626 for(temp_policy = policies; temp_policy != NULL; ){
627 next_policy = temp_policy->next;
628
629 if(strcmp(temp_policy->name, policy) == 0){
630 /* target policy was found */
631
632 /* Clean policy fields */
633 if(temp_policy->rules_list_transformed_to_tree){
634 clean_rules_tree(temp_policy->rules);
635 } else {
636 clean_rules_list(temp_policy->rules);
637 }
638
639 EEF_log(LOG_DEBUG, "Deleted policy: %s\n", policy);
640 free(temp_policy->name);
641 free(temp_policy);
642
643 /* if the head node is deleted, overwrite it with the next node */
644 if(previous_policy){
645 previous_policy->next = next_policy;
646 } else {
647 policies = next_policy;
648 }
649 break;
650 }
651
652 previous_policy = temp_policy;
653
654 /* Move to next policy */
655 temp_policy = next_policy;
656 }
657
658 return policies;
659 }
660
661 /*! converts a string to an array of strings by splitting it at each \t delimiter
662 - overwrites the second argument with a pointer to the number of elements in the array */
663 char** _var_to_argv(char* value, int *argc){
664 char *start_of_arg = NULL, *copy_of_value = NULL, **argv = NULL;
665 char *delimiters = " \t";
666 size_t size_of_arg = 0, size_of_array, i = 0;
667 char *str_ptr;
668
669 copy_of_value = strdup(value);
670 size_of_array = (sizeof(char*)*(strlen(copy_of_value)+1));
671
672 if((argv = calloc(1, size_of_array)) != NULL){
673 start_of_arg = strtok_r(copy_of_value, delimiters, &str_ptr);
674 while(start_of_arg != NULL){
675 size_of_arg = (sizeof(char)*(strlen(start_of_arg)+1));
676 if((argv[i] = calloc(1, size_of_arg))){
677 memcpy(argv[i], start_of_arg, size_of_arg);
678 start_of_arg = strtok_r(NULL, delimiters, &str_ptr);
679 i++;
680 }
681 }
682 }
683 free(copy_of_value);
684 copy_of_value = NULL;
685 if(i < ARG_MAX){
686 *argc = i;
687 } else {
688 *argc = ARG_MAX;
689 }
690 return argv;
691 }
692
693 /*! returns pdl path found in parsed config file */
694 const char* get_pdl_path(){
695 return config.pdl_path;
696 }
697
698 /*! Iterates list of policies and the rules they contain and tries to let the plugin manager prepare plugin structs*/
699 EES_RC add_plugin_structs(){
700 char** argv;
701 int argc;
702 EES_RC plugin_struct_added_ok = EES_SUCCESS;
703 var_t* temp_var = config.variables_list;
704
705 while((temp_var != NULL) && (plugin_struct_added_ok == EES_SUCCESS)){
706 argv = _var_to_argv(temp_var->value, &argc);
707
708 /* this is a callout to the plug-in manager, which adds a struct describing a single plug-in to its list */
709 plugin_struct_added_ok = add_plugin_struct(argc, argv, temp_var->name);
710
711 /* Move to next variable */
712 temp_var = temp_var->next;
713 }
714
715 return plugin_struct_added_ok;
716 }
717
718 /*! Iterates the list of var_t structures and tries to free them */
719 EES_RC clean_variables_list(){
720 config.current_variable = config.variables_list;
721 while(config.current_variable){
722 free(config.current_variable->name);
723 config.current_variable->name = NULL;
724 free(config.current_variable->value);
725 config.current_variable->value = NULL;
726
727 /* Move to next variable */
728 config.variables_list_last = config.current_variable;
729 config.current_variable = config.current_variable->next;
730
731 /* Clean last variable struct */
732 free(config.variables_list_last);
733 config.variables_list_last = NULL;
734 }
735 return EES_SUCCESS;
736 }
737
738 /*! Iterates the tree of rule_t structures starting with the passed rule and tries to free them and their true/false branches */
739 rule_t* clean_rules_tree(rule_t* top_rule){
740 rule_t* temp_rule = top_rule;
741 if(temp_rule){
742 clean_rules_tree(temp_rule->true_branch);
743
744 clean_rules_tree(temp_rule->false_branch);
745
746 free(temp_rule->state);
747 free(temp_rule);
748 temp_rule = NULL;
749 }
750 return NULL;
751 }
752
753 /*! Iterates the list of rule_t structures starting with the passed rule and tries to free them and their true/false branches */
754 rule_t* clean_rules_list(rule_t* top_rule){
755 rule_t *temp_rule = top_rule, *next_rule = NULL;
756 while(temp_rule){
757 next_rule = temp_rule->next;
758 clean_rules_tree(temp_rule);
759 temp_rule = next_rule;
760 }
761 return NULL;
762 }
763
764 void free_args(int argc, char** argv){
765 for(; argc > 0; argc--){
766 free(argv[argc-1]);
767 argv[argc-1] = NULL;
768 }
769 free(argv);
770 argv = NULL;
771 }
772
773 /*! Iterates the list of policy_t structures and tries to free them and their rules */
774 EES_RC clean_policies_list(policy_t* policies){
775 policy_t *temp_policy = policies, *last_policy = NULL;
776 while(temp_policy){
777 /* Clean policy fields */
778 if(temp_policy->rules_list_transformed_to_tree){
779 clean_rules_tree(temp_policy->rules);
780 } else {
781 clean_rules_list(temp_policy->rules);
782 }
783 free(temp_policy->name);
784 temp_policy->name = NULL;
785
786 /* Move to next policy */
787 last_policy = temp_policy;
788 temp_policy = temp_policy->next;
789 free(last_policy);
790 last_policy = NULL;
791 }
792 return EES_SUCCESS;
793 }
794
795 /*! Terminates the parser and tries to free all used memory */
796 EES_RC pdl_term(){
797 clean_variables_list();
798 clean_policies_list(config.policies_list);
799 free(config.pdl_path);
800 config.pdl_path = NULL;
801
802 config.recursion_was_created = 0;
803 config.unknown_variable_was_referenced = 0;
804 config.starting_state_was_reused = 0;
805 config.parse_errors_detected = 0;
806
807 config.variables_list = NULL;
808 config.variables_list_last = NULL;
809 config.current_variable = NULL;
810
811 config.rules_list = NULL;
812 config.rules_list_last = NULL;
813
814 config.policies_list = NULL;
815 config.policies_list_last = NULL;
816
817 if(config.config_file_fp != NULL){
818 /* This is the preferred way of cleaning up various flex versions - See: http://flex.sourceforge.net/manual/Memory-leak-_002d-16386-bytes-allocated-by-malloc_002e.html#Memory-leak-_002d-16386-bytes-allocated-by-malloc_002e */
819 #if HAVE_YYLEX_DESTROY /* macro set by configure script */
820 yylex_destroy();
821 #else
822 /*eef_log(LOG_WARNING, "Lex function yylex_destroy() not available - possibly unable to free allocated memory for evaluation manager\n");*/
823 #if HAVE_FLEX
824 delete_lex_buffer(); /* this function is defined in pdl_lex.l */
825 /*eef_log(LOG_INFO, "Managed to free allocated memory for evaluation manager\n"); */
826 #else
827 EEF_log(LOG_WARNING, "Lex functions yylex_destroy() and yy_delete_buffer() are both not available - unable to free allocated memory for evaluation manager\n");
828 #endif
829 #endif
830
831 if((fclose(config.config_file_fp)==0) ){
832 return EES_SUCCESS;
833 }
834 }
835 return EES_FAILURE;
836 }
837
838 /*! TODO */
839 EES_RC allow_rules(int val){
840 /*eef_log(LOG_DEBUG, "Allowed rule: %i\n", val);*/
841 return EES_SUCCESS;
842 }
843
844 /*! TODO */
845 EES_RC allowed_policy_rule(const char* label){
846 /*eef_log(LOG_DEBUG, "Allowed policy rule: %s\n", label);*/
847 return EES_SUCCESS;
848 }

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