Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

pdl_main.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) Members of the EGEE Collaboration. 2004.
00003  * See http://eu-egee.org/partners/ for details on the copyright holders.
00004  * For license conditions see the license file or
00005  * http://eu-egee.org/license.html
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2003 EU DataGrid        http://www.eu-datagrid.org/
00010  *
00011  *   $Id: pdl_main.c,v 1.42 2005/03/01 17:05:10 venekamp Exp $
00012  *
00013  *   Copyright (c) 2003 by
00014  *      G.M. Venekamp <venekamp@nikhef.nl>
00015  *      NIKHEF Amsterdam, the Netherlands
00016  *
00017  *   This software is distributed under a BSD-style open source
00018  *   licence. For a complete description of the licence take a look
00019  *   at: http://eu-datagrid.web.cern.ch/eu-datagrid/license.html
00020  *
00021  */
00022 
00023 
00041 #include <stdarg.h>
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 
00046 #include "_lcmaps_pluginmanager.h"
00047 #include "lcmaps_log.h"
00048 #include "pdl.h"
00049 #include "pdl_variable.h"
00050 #include "pdl_policy.h"
00051 #include "pdl_rule.h"
00052 
00053 static const char* script_name  = NULL;           
00054 static const char* d_path       = "/usr/lib";     
00055 static const char* path         = 0;              
00056 static int path_lineno          = 0;              
00057 static plugin_t* top_plugin     = NULL;           
00058 static BOOL default_path        = TRUE;           
00059 static BOOL parse_error         = FALSE;          
00060 static char* level_str[PDL_SAME];                 
00061 
00062 static const policy_t* current_policy = 0;
00063 static const rule_t*   current_rule   = 0;
00064 
00065 unsigned int lineno = 1;   
00066 
00067 void _set_path(const record_t* _path);
00068 record_t* _concat_strings(const record_t* s1, const record_t* s2, const char* extra);
00069 void reduce_policies(void);
00070 void init_name_args(plugin_t** plugin, const rule_t* rule, rule_type_t type);
00071 BOOL plugin_exists(const char* string);
00072 int find_first_space(const char* string);
00073 
00074 
00079 const policy_t* get_current_policy(void)
00080 {
00081   return current_policy;
00082 }
00083 
00093 int pdl_init(const char* name)
00094 {
00095   if (name) {
00096     FILE* file;
00097 
00098     script_name = strdup(name);
00099 
00100     file = fopen(name, "r");
00101     if (file)
00102       yyin = file;
00103     else {
00104       warning(PDL_ERROR, "Could not open file '%s'.", name);
00105       return -1;
00106     }
00107   }
00108 
00109   /*  Set the default path  */
00110   path = d_path;
00111   default_path = TRUE;
00112 
00113   /*
00114    *  Check if there are plugins, if so clear top_plugin and free
00115    *  all allocated memory.
00116    */
00117   if (top_plugin) free_plugins(&top_plugin);
00118 //  while (top_plugin) {
00119 //    if (top_plugin->name) { free(top_plugin->name); }
00120 //    if (top_plugin->args) { free(top_plugin->args); }
00121 //    top_plugin = top_plugin->next;
00122 //  }
00123 
00124   /*  Init the levels with the appropriate print text.  */
00125   level_str[PDL_INFO]    = "info";
00126   level_str[PDL_WARNING] = "warning";
00127   level_str[PDL_ERROR]   = "error";
00128   level_str[PDL_UNKNOWN] = "<unknown>";
00129 
00130   parse_error = FALSE;
00131 
00132   return 0;
00133 }
00134 
00135 
00142 int yyparse_errors(void)
00143 {
00144   return parse_error ? -1 : 0;
00145 }
00146 
00147 
00154 const plugin_t* get_plugins(void)
00155 {
00156   plugin_t* plugin;
00157   policy_t* policy;
00158 
00159   /*
00160    *  Check if the policies have been reduced. If not, then getting
00161    *  the plugins and their arguments is useless; the variables have
00162    *  not been substituted yet.
00163    */
00164   if (!policies_have_been_reduced()) {
00165     lcmaps_log(1, "The policies have not been reduced. Probably the startElevaluationManager has failed or has not been called yet.\n");
00166     return 0;
00167   }
00168 
00169   /*
00170    *  Check if evaluation has been done before, if so use the old
00171    *  results.
00172    */
00173   if (top_plugin)
00174     return top_plugin;
00175 
00176   policy = get_policies();
00177 
00178   while (policy) {
00179     rule_t* rule = policy->rule;
00180 
00181     lcmaps_log_debug(1, "processing policy: %s\n", policy->name);
00182     while (rule) {
00183       lcmaps_log_debug(1, "  processing rule: %s -> %s | %s\n", rule->state, rule->true_branch, rule->false_branch);
00184 
00185       lcmaps_log_debug(1, "  get_plugins:  initializing...\n");
00186       init_name_args(&plugin, rule, STATE);
00187       init_name_args(&plugin, rule, TRUE_BRANCH);
00188       init_name_args(&plugin, rule, FALSE_BRANCH);
00189       lcmaps_log_debug(1, "  get_plugins:  initializing done.\n");
00190 
00191       rule = rule->next;
00192     }
00193     policy = policy->next;
00194   }
00195 
00196   return top_plugin;
00197 }
00198 
00209 int free_plugins(
00210         plugin_t ** list
00211 )
00212 {
00213     plugin_t * p_list     = NULL;
00214     plugin_t * tmp_p_list = NULL;
00215 
00216     p_list = *list;
00217     while (p_list) {
00218         tmp_p_list = p_list->next;
00219 
00220         lcmaps_log_debug(3, "freeing plugin %s at address %p\n", p_list->name, p_list);
00221         if (p_list->name){
00222             free(p_list->name);
00223             p_list->name = NULL;
00224         }
00225         if (p_list->args){
00226             free(p_list->args);
00227             p_list->args = NULL;
00228         }
00229         p_list->next = NULL;
00230         free((plugin_t*)p_list);
00231 
00232         p_list = tmp_p_list;
00233     }
00234     *list=p_list=NULL;
00235     return 0;
00236 }
00237 
00245 BOOL plugin_exists(const char* string)
00246 {
00247   int space, remainder;
00248   plugin_t *plugin;
00249 
00250   space     = find_first_space(string);
00251   remainder = strlen(string) - space - 1;
00252   plugin    = top_plugin;
00253 
00254   while (plugin) {
00255     if (plugin->name && strncmp(plugin->name, string, space)==0) {
00256       if (plugin->args)
00257         if (strncmp(plugin->args, string+space+1, remainder)!=0) {
00258           plugin = plugin->next;
00259           continue;
00260         }
00261       return TRUE;
00262     }
00263     plugin = plugin->next;
00264   }
00265 
00266   return FALSE;
00267 }
00268 
00269 
00273 void init_name_args(plugin_t** plugin, const rule_t* rule, rule_type_t type)
00274 {
00275   int space, remainder;
00276   const char* string;
00277 
00278   switch (type) {
00279   case STATE:
00280     string = rule->state;
00281     break;
00282   case TRUE_BRANCH:
00283     string = rule->true_branch;
00284     break;
00285   case FALSE_BRANCH:
00286     string = rule->false_branch;
00287     break;
00288   default:
00289     warning(PDL_ERROR, "init_name_args: unknown type!");
00290     return;
00291   }
00292 
00293   lcmaps_log_debug(1, "  init_name_args: processing: %s\n", string);
00294 
00295   if (!string || plugin_exists(string)) {
00296     lcmaps_log_debug(1, "  init_name_args: Either the plugin exists or string == 0.\n");
00297     return;
00298   }
00299 
00300   lcmaps_log_debug(1, "  init_name_args: plugin does not exists.\n");
00301 
00302   if (!top_plugin) {
00303     top_plugin = (plugin_t*)malloc(sizeof(plugin_t));
00304     *plugin = top_plugin;
00305   }
00306   else {
00307     (*plugin)->next = (plugin_t*)malloc(sizeof(plugin_t));
00308     *plugin = (*plugin)->next;
00309   }
00310 
00311   (*plugin)->name = (*plugin)->args = 0;
00312   (*plugin)->next = 0;
00313 
00314   space = find_first_space(string);
00315 
00316   lcmaps_log_debug(1, "  init_name_args: space found a pos: %d  strlen = %d.\n", space, strlen(string));
00317 
00318   (*plugin)->name = (char *)malloc(space+1);
00319   strncpy((*plugin)->name, string, space);
00320   *((*plugin)->name+space) = '\0';
00321 
00322   remainder = strlen(string)-space-1;
00323   if (remainder > 0) {
00324     (*plugin)->args   = (char *)malloc(remainder+1);
00325     strncpy((*plugin)->args, string+space+1, remainder);
00326     *((*plugin)->args+remainder) = '\0';
00327   } else
00328     (*plugin)->args = 0;
00329 
00330   (*plugin)->lineno = rule->lineno;
00331   (*plugin)->next   = 0;
00332 
00333   lcmaps_log_debug(1, "  init_name_args: plugin->name = %s\n", (*plugin)->name);
00334   lcmaps_log_debug(1, "  init_name_args: plugin->args = %s\n", (*plugin)->args);
00335 }
00336 
00337 
00347 int find_first_space(const char* string)
00348 {
00349   int space, max_length;
00350   space = 0;
00351   max_length = strlen(string);
00352 
00353   for (; *string++ != ' ' && space < max_length; ++space);
00354 
00355   return space;
00356 }
00357 
00358 
00364 const char *pdl_path(void)
00365 {
00366   return path;
00367 };
00368 
00369 
00377 int yyerror(const char* s)
00378 {
00379   //  lcmaps_log_debug(1, "%s\n", token_name());
00380 
00381   warning(PDL_ERROR, s);
00382 
00383   return 0;
00384 }
00385 
00386 
00394 void set_path(record_t* path)
00395 {
00396   _set_path(path);
00397 
00398   free(path->string);
00399   free(path);
00400 }
00401 
00402 
00411 void _set_path(const record_t* _path)
00412 {
00413   //  lcmaps_log_debug(1, "set_path: '%s'.\n", _path);
00414 
00415   if (!default_path) {
00416     warning(PDL_ERROR, "path already defined in: %d; ignoring this instance.", path_lineno);
00417     return;
00418   }
00419 
00420   default_path = FALSE;
00421   path_lineno  = _path->lineno;
00422   path         = strdup(_path->string);
00423 }
00424 
00425 
00426 
00430 void free_path(void)
00431 {
00432   if (!default_path && path) {
00433     free((char*)path);
00434     default_path = TRUE;
00435     path = 0;
00436   }
00437 }
00438 
00439 
00440 
00451 record_t* concat_strings(record_t* s1, record_t* s2)
00452 {
00453   record_t* r = _concat_strings(s1, s2, 0);
00454 
00455   free(s1->string);
00456   free(s2->string);
00457   free(s1);
00458   free(s2);
00459 
00460   return r;
00461 }
00462 
00463 
00473 record_t* _concat_strings(const record_t* s1, const record_t* s2,
00474                           const char* extra)
00475 {
00476   int len       = strlen(s1->string);
00477   int len_extra = extra ? strlen(extra) : 0;
00478 
00479   record_t* record = (record_t *)malloc(sizeof(record_t));
00480 
00481   if (!(record->string = (char *)malloc(len + len_extra + strlen(s2->string)+1))) {
00482     warning(PDL_ERROR, "out of memory");
00483     return 0;
00484   }
00485 
00486   strcpy(record->string, s1->string);
00487   if (extra)
00488     strcpy(record->string+len, extra);
00489   strcpy(record->string+len+len_extra, s2->string);
00490 
00491   //lcmaps_log_debug(1, "concat_strings: '%s' + '%s' = '%s'.\n", s1, s2, s3);
00492 
00493   return record;
00494 }
00495 
00496 
00507 record_t* concat_strings_with_space(record_t* s1, record_t* s2)
00508 {
00509   record_t* r;
00510 
00511   /*  Check if there is a string to add.  */
00512   if (strlen(s2->string)!=0) {
00513     /*
00514      *  When the first and second string end with ", do not an extra
00515      *  space. This is the result of an sequence of escaped ".
00516      */
00517     if ((s1->string[strlen(s1->string)-1]=='"') &&
00518         (s2->string[strlen(s2->string)-1]=='"'))
00519       r = _concat_strings(s1, s2, 0);
00520     else
00521       r = _concat_strings(s1, s2, " ");
00522 
00523     free(s1->string);
00524     free(s2->string);
00525     free(s1);
00526     free(s2);
00527   } else {
00528     /*
00529      *  Since there is nothing to concatenate, we simply copy the
00530      *  first string (s1) to the result.
00531      */
00532     r = (record_t*)malloc(sizeof(r));
00533     memcpy(r, s1, sizeof(r));
00534   }
00535 
00536   return r;
00537 }
00538 
00539 
00557 const char* pdl_next_plugin(plugin_status_t status)
00558 {
00559   char* string      = 0;
00560   const char* state = 0;
00561 
00562   switch (status) {
00563   case EVALUATION_START:
00564     /*  Make sure that there is a policy list.  */
00565     if (!(current_policy = get_policies()))
00566       return 0;
00567     if (!(current_rule = current_policy->rule))
00568       return 0;
00569 
00570     state = current_rule->state;
00571     break;
00572 
00573   case EVALUATION_SUCCESS:
00574     if (current_rule)
00575       state = current_rule->true_branch;
00576 
00577     if (current_policy && state)
00578       current_rule = find_state(current_policy->rule, state);
00579     else
00580       current_rule = 0;
00581     break;
00582 
00583   case EVALUATION_FAILURE:
00584     /*
00585      *  Find the next rule for evalaution. The plugins specified by
00586      *  that rule will not be returned by this iterating of the
00587      *  function. Instead the static/global variables are setup, such
00588      *  that on the next iteration the next plugin is returned. Only
00589      *  after the evaluation of the plugin found during this iteration
00590      *  can a decision be made which plugin to return.
00591      *
00592      *  When the last rule has been evaluated, there is the
00593      *  possibility that there is another policy in the configration.
00594      *  Instead of stopping at the end of a rule chain, setup the
00595      *  variables for the next policy rule.
00596      *
00597      */
00598     if (current_rule)
00599       state = current_rule->false_branch;
00600 
00601     /* 
00602      *  Check if either there is a current_rule or a state. If so, we
00603      *  can continue. If there is no current rule, there might be a
00604      *  next policy. This needs to be evaluated next. If there is no
00605      *  state, this is because the false branch does not exist and
00606      *  hence we need to evaluate possible next policies.
00607      *
00608      */
00609     if (!(current_rule && state)) {
00610       if (current_policy && (current_policy = current_policy->next)) {
00611         if ((current_rule = current_policy->rule)) {
00612           int rc;
00613           state = current_rule->state;
00614           lcmaps_log_debug(1, "evaluationmanager: Resetting credential data for policy: %s\n", current_policy->name);
00615           rc = resetCredentialData();
00616           
00617           if (rc) {
00618             warning(PDL_ERROR, "Resetting credential data failed: rc = %d", rc);
00619             return 0;
00620           }
00621         }
00622       }
00623     } else {
00624        /*  We have a valid next state. Let's find the next rule.  */
00625       if (current_policy)
00626         current_rule = find_state(current_policy->rule, state);
00627     }
00628 
00629     break;
00630   }
00631 
00632   /*
00633    *  Create the full plugin name, i.e. including the path. The rules
00634    *  do not specify the path, this must be added so that a single
00635    *  string can be returned. State holde the current plugin name.
00636    *
00637    */
00638   if (state) {
00639     const char* tmp;
00640     int state_length, path_length;
00641 
00642     tmp = state;
00643     state_length = path_length = 0;
00644 
00645     while (*tmp!=' ' && *tmp++!='\0') {
00646       ++state_length;
00647     }
00648     path_length = strlen(pdl_path());
00649 
00650     /*  Allocate memory and initialize the string.  */
00651     string = (char*)malloc(state_length + path_length + 2);
00652     strcpy(string, pdl_path());
00653 
00654     /*  Make sure the path ends in '/'.  */
00655     if (string[path_length-1] != '/')
00656       string[path_length++] = '/';
00657     strncpy(string + path_length, state, state_length);
00658     string[path_length + state_length] = '\0';
00659 
00660     lcmaps_log_debug(1, "evaluationmanager: found plugin: %s\n", string);
00661   }
00662 
00663   return string;
00664 }
00665 
00666 
00671 void free_resources(void)
00672 {
00673   if (script_name) {
00674     free((char*)script_name);
00675     script_name = 0;
00676   }
00677 
00678   free_path();
00679 
00680   free_variables();
00681   free_policies();
00682 
00683   free_plugins(&top_plugin);
00684 
00685   /*
00686    *  YACC takes its input from the stdin by default. When the input
00687    *  is taken from a file, the yyin variable will have a different
00688    *  value from stdin and stderr. If so, it is necessary to close it.
00689    */
00690   if (yyin!=stdin && yyin!=stderr) {
00691     if (yyin)
00692         fclose(yyin);
00693     yyin=stdin;
00694   }
00695 
00696 #ifdef HAVE_FLEX
00697   delete_lex_buffer();
00698 #endif
00699 }
00700 
00701 
00710 void warning(pdl_error_t error, const char* s, ...)
00711 {
00712   static char* level = 0;
00713   char buf[2048];
00714   int res;
00715 
00716   va_list args;
00717 
00718   if (error == PDL_ERROR)
00719     parse_error = TRUE;
00720 
00721   if (!level)
00722     level = level_str[PDL_UNKNOWN];
00723 
00724   if (error != PDL_SAME)
00725     level = level_str[error];
00726 
00727   /*
00728    *  Prepend a standard text before the message. This makes reading
00729    *  the errors/warnings a little easier.
00730    */
00731   res = sprintf(buf, "%s:%d: [%s] ", script_name, lineno, level);
00732 
00733   /*  Print (format) the actual message.  */
00734   va_start(args, s);
00735   res += vsnprintf(buf+res, sizeof(buf)-res-2, s, args);
00736   va_end(args);
00737 
00738   /*
00739    *  The string needs to end in a new line and of course strings are
00740    *  termintated by the end of string character. Make sure it happens
00741    *  and respect the buffer size!
00742    */
00743   buf[res<sizeof(buf)-1 ? res++ : sizeof(buf)-2] = '\n';
00744   buf[res<sizeof(buf)   ? res   : sizeof(buf)-1] = '\0';
00745 
00746   lcmaps_log(0, buf);
00747 }
00748 

Generated on Sun May 29 21:22:11 2005 for lcmaps by doxygen 1.3.5