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) 2003 EU DataGrid        http://www.eu-datagrid.org/
00003  *
00004  *   $Id: pdl_main.c,v 1.34 2003/10/07 11:21:17 venekamp Exp $
00005  *
00006  *   Copyright (c) 2003 by
00007  *      G.M. Venekamp <venekamp@nikhef.nl>
00008  *      NIKHEF Amsterdam, the Netherlands
00009  *
00010  *   This software is distributed under a BSD-style open source
00011  *   licence. For a complete description of the licence take a look
00012  *   at: http://eu-datagrid.web.cern.ch/eu-datagrid/license.html
00013  *
00014  */
00015 
00016 
00034 #include <stdarg.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #include "_lcmaps_pluginmanager.h"
00040 #include "lcmaps_log.h"
00041 #include "pdl.h"
00042 #include "pdl_variable.h"
00043 #include "pdl_policy.h"
00044 #include "pdl_rule.h"
00045 
00046 static const char* script_name  = NULL;           
00047 static const char* d_path       = "/usr/lib";     
00048 static const char* path         = 0;              
00049 static int path_lineno          = 0;              
00050 static plugin_t* top_plugin     = NULL;           
00051 static BOOL default_path        = TRUE;           
00052 static BOOL parse_error         = FALSE;          
00053 static char* level_str[PDL_SAME];                 
00054 
00055 unsigned int lineno = 1;   
00056 
00057 void _set_path(const record_t* _path);
00058 record_t* _concat_strings(const record_t* s1, const record_t* s2, const char* extra);
00059 void reduce_policies(void);
00060 void init_name_args(plugin_t** plugin, const rule_t* rule, rule_type_t type);
00061 BOOL plugin_exists(const char* string);
00062 int find_first_space(const char* string);
00063 
00064 
00074 int pdl_init(const char* name)
00075 {
00076   if (name) {
00077     FILE* file;
00078 
00079     script_name = strdup(name);
00080 
00081     file = fopen(name, "r");
00082     if (file)
00083       yyin = file;
00084     else {
00085       warning(PDL_ERROR, "Could not open file '%s'.", name);
00086       return -1;
00087     }
00088   }
00089 
00090   /*  Set the default path  */
00091   path = d_path;
00092   default_path = TRUE;
00093 
00094   /*
00095    *  Check if there are plugins, if so clear top_plugin and free
00096    *  all allocated memory.
00097    */
00098   while (top_plugin) {
00099     free(top_plugin->name);
00100     free(top_plugin->args);
00101     top_plugin = top_plugin->next;
00102   }
00103 
00104   /*  Init the levels with the appropriate print text.  */
00105   level_str[PDL_INFO]    = "info";
00106   level_str[PDL_WARNING] = "warning";
00107   level_str[PDL_ERROR]   = "error";
00108   level_str[PDL_UNKNOWN] = "<unknown>";
00109 
00110   parse_error = FALSE;
00111 
00112   return 0;
00113 }
00114 
00115 
00122 int yyparse_errors(void)
00123 {
00124   return parse_error ? -1 : 0;
00125 }
00126 
00127 
00134 const plugin_t* get_plugins(void)
00135 {
00136   plugin_t* plugin;
00137   policy_t* policy;
00138 
00139   /*
00140    *  Check if the policies have been reduced. If not, then getting
00141    *  the plugins and their arguments is useless; the variables have
00142    *  not been substituted yet.
00143    */
00144   if (!policies_have_been_reduced()) {
00145     lcmaps_log(1, "The policies have not been reduced. Probably the startElevaluationManager has failed or has not been called yet.\n");
00146     return 0;
00147   }
00148 
00149   /*
00150    *  Check if evaluation has been done before, if so use the old
00151    *  results.
00152    */
00153   if (top_plugin)
00154     return top_plugin;
00155 
00156   policy = get_policies();
00157 
00158   while (policy) {
00159     rule_t* rule = policy->rule;
00160 
00161     lcmaps_log_debug(1, "processing policy: %s\n", policy->name);
00162     while (rule) {
00163       lcmaps_log_debug(1, "  processing rule: %s -> %s | %s\n", rule->state, rule->true_branch, rule->false_branch);
00164 
00165       lcmaps_log_debug(1, "  get_plugins:  initializing...\n");
00166       init_name_args(&plugin, rule, STATE);
00167       init_name_args(&plugin, rule, TRUE_BRANCH);
00168       init_name_args(&plugin, rule, FALSE_BRANCH);
00169       lcmaps_log_debug(1, "  get_plugins:  initializing done.\n");
00170 
00171       rule = rule->next;
00172     }
00173     policy = policy->next;
00174   }
00175   
00176   return top_plugin;
00177 }
00178 
00179 
00187 BOOL plugin_exists(const char* string)
00188 {
00189   int space, remainder;
00190   plugin_t *plugin;
00191 
00192   space     = find_first_space(string);
00193   remainder = strlen(string) - space - 1;
00194   plugin    = top_plugin;
00195 
00196   while (plugin) {
00197     if (plugin->name && strncmp(plugin->name, string, space)==0) {
00198       if (plugin->args)
00199         if (strncmp(plugin->args, string+space+1, remainder)!=0) {
00200           plugin = plugin->next;
00201           continue;
00202         }
00203       return TRUE;
00204     }
00205     plugin = plugin->next;
00206   }
00207   
00208   return FALSE;
00209 }
00210 
00211 
00215 void init_name_args(plugin_t** plugin, const rule_t* rule, rule_type_t type)
00216 {
00217   int space, remainder;
00218   const char* string;
00219 
00220   switch (type) {
00221   case STATE:
00222     string = rule->state;
00223     break;
00224   case TRUE_BRANCH:
00225     string = rule->true_branch;
00226     break;
00227   case FALSE_BRANCH:
00228     string = rule->false_branch;
00229     break;
00230   default:
00231     warning(PDL_ERROR, "init_name_args: unknown type!");
00232     return;
00233   }
00234 
00235   lcmaps_log_debug(1, "  init_name_args: processing: %s\n", string);
00236 
00237   if (!string || plugin_exists(string)) {
00238     lcmaps_log_debug(1, "  init_name_args: Either the plugin exists or string == 0.\n");
00239     return;
00240   }
00241 
00242   lcmaps_log_debug(1, "  init_name_args: plugin does not exists.\n");
00243 
00244   if (!top_plugin) {
00245     top_plugin = (plugin_t*)malloc(sizeof(plugin_t));
00246     *plugin = top_plugin;
00247   }
00248   else {
00249     (*plugin)->next = (plugin_t*)malloc(sizeof(plugin_t));
00250     *plugin = (*plugin)->next;
00251   }
00252 
00253   (*plugin)->name = (*plugin)->args = 0;
00254   (*plugin)->next = 0;
00255 
00256   space = find_first_space(string);
00257 
00258   lcmaps_log_debug(1, "  init_name_args: space found a pos: %d  strlen = %d.\n", space, strlen(string));
00259 
00260   (*plugin)->name = (char *)malloc(space+1);
00261   strncpy((*plugin)->name, string, space);
00262   *((*plugin)->name+space) = '\0';
00263   
00264   remainder = strlen(string)-space-1;
00265   if (remainder > 0) {
00266     (*plugin)->args   = (char *)malloc(remainder+1);
00267     strncpy((*plugin)->args, string+space+1, remainder);
00268     *((*plugin)->args+remainder) = '\0';
00269   } else
00270     (*plugin)->args = 0;
00271 
00272   (*plugin)->lineno = rule->lineno;
00273   (*plugin)->next   = 0;
00274 
00275   lcmaps_log_debug(1, "  init_name_args: plugin->name = %s\n", (*plugin)->name);
00276   lcmaps_log_debug(1, "  init_name_args: plugin->args = %s\n", (*plugin)->args);
00277 }
00278 
00279 
00289 int find_first_space(const char* string)
00290 {
00291   int space, max_length;
00292   space = 0;
00293   max_length = strlen(string);
00294 
00295   for (; *string++ != ' ' && space < max_length; ++space);
00296 
00297   return space;
00298 }
00299 
00300 
00306 const char *pdl_path(void)
00307 {
00308   return path;
00309 };
00310 
00311 
00319 int yyerror(const char* s)
00320 {
00321   //  lcmaps_log_debug(1, "%s\n", token_name());
00322 
00323   warning(PDL_ERROR, s);
00324 
00325   return 0;
00326 }
00327 
00328 
00336 void set_path(record_t* path)
00337 {
00338   _set_path(path);
00339 
00340   free(path->string);
00341   free(path);
00342 }
00343 
00344 
00353 void _set_path(const record_t* _path)
00354 {
00355   //  lcmaps_log_debug(1, "set_path: '%s'.\n", _path);
00356 
00357   if (!default_path) {
00358     warning(PDL_ERROR, "path already defined in: %d; ignoring this instance.", path_lineno);
00359     return;
00360   }
00361 
00362   default_path = FALSE;
00363   path_lineno  = _path->lineno;
00364   path         = strdup(_path->string);
00365 }
00366 
00367 
00368 
00372 void free_path(void)
00373 {
00374   if (!default_path && path) {
00375     free((char*)path);
00376     default_path = TRUE;
00377     path = 0;
00378   }
00379 }
00380 
00381 
00382 
00393 record_t* concat_strings(record_t* s1, record_t* s2)
00394 {
00395   record_t* r = _concat_strings(s1, s2, 0);
00396 
00397   free(s1->string);
00398   free(s2->string);
00399   free(s1);
00400   free(s2);
00401 
00402   return r;
00403 }
00404 
00405 
00414 record_t* _concat_strings(const record_t* s1, const record_t* s2,
00415                           const char* extra)
00416 {
00417   int len       = strlen(s1->string);
00418   int len_extra = extra ? strlen(extra) : 0;
00419 
00420   record_t* record = (record_t *)malloc(sizeof(record_t));
00421 
00422   if (!(record->string = (char *)malloc(len + len_extra + strlen(s2->string)+1))) {
00423     warning(PDL_ERROR, "out of memory");
00424     return 0;
00425   }
00426 
00427   strcpy(record->string, s1->string);
00428   if (extra)
00429     strcpy(record->string+len, extra);
00430   strcpy(record->string+len+len_extra, s2->string);
00431 
00432   //lcmaps_log_debug(1, "concat_strings: '%s' + '%s' = '%s'.\n", s1, s2, s3);
00433 
00434   return record;
00435 }
00436 
00437 
00448 record_t* concat_strings_with_space(record_t* s1, record_t* s2)
00449 {
00450   record_t* r;
00451 
00452   /*  Check if there is a string to add.  */
00453   if (strlen(s2->string)!=0) {
00454     /*
00455      *  When the first and second string end with ", do not an extra
00456      *  space. This is the result of an sequence of escaped ".
00457      */
00458     if ((s1->string[strlen(s1->string)-1]=='"') &&
00459         (s2->string[strlen(s2->string)-1]=='"'))
00460       r = _concat_strings(s1, s2, 0);
00461     else
00462       r = _concat_strings(s1, s2, " ");
00463 
00464     free(s1->string);
00465     free(s2->string);
00466     free(s1);
00467     free(s2);
00468   } else {
00469     /*
00470      *  Since there is nothing to concatenate, we simply copy the
00471      *  first string (s1) to the result.
00472      */
00473     r = (record_t*)malloc(sizeof(r));
00474     memcpy(r, s1, sizeof(r));
00475   }
00476 
00477   return r;
00478 }
00479 
00480 
00498 const char* pdl_next_plugin(plugin_status_t status)
00499 {
00500   const static policy_t* current_policy = 0;
00501   const static rule_t*   current_rule   = 0;
00502   char* string      = 0;
00503   const char* state = 0;
00504 
00505   switch (status) {
00506   case EVALUATION_START:
00507     /*  Make sure that there is a policy list.  */
00508     if (!(current_policy = get_policies()))
00509       return 0;
00510     if (!(current_rule = current_policy->rule))
00511       return 0;
00512 
00513     state = current_rule->state;
00514     break;
00515 
00516   case EVALUATION_SUCCESS:
00517     if (current_rule)
00518       state = current_rule->true_branch;
00519 
00520     if (current_policy && state)
00521       current_rule = find_state(current_policy->rule, state);
00522     else
00523       current_rule = 0;
00524     break;
00525 
00526   case EVALUATION_FAILURE:
00527     /*
00528      *  Find the next rule for evalaution. The plugins specified by
00529      *  that rule will not be returned by this iterating of the
00530      *  function. Instead the static variables are setup, such that on
00531      *  the next iteration the next plugin is returned. Only after the
00532      *  evaluation of the plugin found during this iteration can a
00533      *  decision be made which plugin to return.
00534      *
00535      *  When the last rule has been evaluated, there is the
00536      *  possibility that there is another policy in the configration.
00537      *  Instead of stopping at the end of a rule chain, setup the
00538      *  variables for the next policy rule.
00539      *
00540      */
00541     if (current_rule)
00542       state = current_rule->false_branch;
00543 
00544     /* 
00545      *  Check if either there is a current_rule or a state. If so, we
00546      *  can continue. If there is no current rule, there might be a
00547      *  next policy. This needs to be evaluated next. If there is no
00548      *  state, this is because the false branch does not exist and
00549      *  hence we need to evaluate possible next policies.
00550      *
00551      */
00552     if (!(current_rule && state)) {
00553       if (current_policy && (current_policy = current_policy->next)) {
00554         if ((current_rule = current_policy->rule)) {
00555           int rc;
00556           state = current_rule->state;
00557           lcmaps_log_debug(1, "evaluationmanager: Resetting credential data for policy: %s\n", current_policy->name);
00558           rc = resetCredentialData();
00559           
00560           if (rc) {
00561             warning(PDL_ERROR, "Resetting credential data failed: rc = %d", rc);
00562             return 0;
00563           }
00564         }
00565       }
00566     } else {
00567        /*  We have a valid next state. Let's find  the next rule.  */
00568       if (current_policy)
00569         current_rule = find_state(current_policy->rule, state);
00570     }
00571 
00572     break;
00573   }
00574 
00575   /*
00576    *  Create the full plugin name, i.e. including the path. The rules
00577    *  do not specify the path, this must be added so that a single
00578    *  string can be returned. State holde the current plugin name.
00579    *
00580    */
00581   if (state) {
00582     const char* tmp;
00583     int state_length, path_length;
00584 
00585     tmp = state;
00586     state_length = path_length = 0;
00587 
00588     while (*tmp!=' ' && *tmp++!='\0') {
00589       ++state_length;
00590     }
00591     path_length = strlen(pdl_path());
00592 
00593     /*  Allocate memory and initialize the string.  */
00594     string = (char*)malloc(state_length + path_length + 2);
00595     strcpy(string, pdl_path());
00596 
00597     /*  Make sure the path ends in '/'.  */
00598     if (string[path_length-1] != '/')
00599       string[path_length++] = '/';
00600     strncpy(string + path_length, state, state_length);
00601     string[path_length + state_length] = '\0';
00602   }
00603 
00604   return string;
00605 }
00606 
00607 
00612 void free_resources(void)
00613 {
00614   if (script_name) {
00615     free((char*)script_name);
00616     script_name = 0;
00617   }
00618 
00619   free_path();
00620 
00621   free_variables();
00622   free_policies();
00623 
00624   /*
00625    *  YACC takes its input from the stdin by default. When the input
00626    *  is taken from a file, the yyin variable will have a different
00627    *  value from stdin and stderr. If so, it is necessary to close it.
00628    */
00629   if (yyin!=stdin && yyin!=stderr) {
00630     fclose(yyin);
00631     yyin=stdin;
00632   }
00633 
00634 #ifdef HAVE_FLEX
00635   delete_lex_buffer();
00636 #endif
00637 }
00638 
00639 
00648 void warning(pdl_error_t error, const char* s, ...)
00649 {
00650   static char* level = 0;
00651   char buf[2048];
00652   int res;
00653 
00654   va_list args;
00655 
00656   if (error == PDL_ERROR)
00657     parse_error = TRUE;
00658 
00659   if (!level)
00660     level = level_str[PDL_UNKNOWN];
00661 
00662   if (error != PDL_SAME)
00663     level = level_str[error];
00664 
00665   /*
00666    *  Prepend a standard text before the message. This makes reading
00667    *  the errors/warnings a little easier.
00668    */
00669   res = sprintf(buf, "%s:%d: [%s] ", script_name, lineno, level);
00670 
00671   /*  Print (format) the actual message.  */
00672   va_start(args, s);
00673   res += vsnprintf(buf+res, sizeof(buf)-res-2, s, args);
00674   va_end(args);
00675 
00676   /*
00677    *  The string needs to end in a new line and of course strings are
00678    *  termintated by the end of string character. Make sure it happens
00679    *  and respect the buffer size!
00680    */
00681   buf[res<sizeof(buf)-1 ? res++ : sizeof(buf)-2] = '\n';
00682   buf[res<sizeof(buf)   ? res   : sizeof(buf)-1] = '\0';
00683 
00684   lcmaps_log(0, buf);
00685 }
00686 

Generated at Thu Mar 4 17:39:03 2004 for edg-lcmaps by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001