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.36 2004/10/01 15:17:31 maart 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 static const policy_t* current_policy = 0;
00056 static const rule_t*   current_rule   = 0;
00057 
00058 unsigned int lineno = 1;   
00059 
00060 void _set_path(const record_t* _path);
00061 record_t* _concat_strings(const record_t* s1, const record_t* s2, const char* extra);
00062 void reduce_policies(void);
00063 void init_name_args(plugin_t** plugin, const rule_t* rule, rule_type_t type);
00064 BOOL plugin_exists(const char* string);
00065 int find_first_space(const char* string);
00066 
00067 
00072 policy_t* get_current_policy(void)
00073 {
00074   return current_policy;
00075 }
00076 
00086 int pdl_init(const char* name)
00087 {
00088   if (name) {
00089     FILE* file;
00090 
00091     script_name = strdup(name);
00092 
00093     file = fopen(name, "r");
00094     if (file)
00095       yyin = file;
00096     else {
00097       warning(PDL_ERROR, "Could not open file '%s'.", name);
00098       return -1;
00099     }
00100   }
00101 
00102   /*  Set the default path  */
00103   path = d_path;
00104   default_path = TRUE;
00105 
00106   /*
00107    *  Check if there are plugins, if so clear top_plugin and free
00108    *  all allocated memory.
00109    */
00110   while (top_plugin) {
00111     free(top_plugin->name);
00112     free(top_plugin->args);
00113     top_plugin = top_plugin->next;
00114   }
00115 
00116   /*  Init the levels with the appropriate print text.  */
00117   level_str[PDL_INFO]    = "info";
00118   level_str[PDL_WARNING] = "warning";
00119   level_str[PDL_ERROR]   = "error";
00120   level_str[PDL_UNKNOWN] = "<unknown>";
00121 
00122   parse_error = FALSE;
00123 
00124   return 0;
00125 }
00126 
00127 
00134 int yyparse_errors(void)
00135 {
00136   return parse_error ? -1 : 0;
00137 }
00138 
00139 
00146 const plugin_t* get_plugins(void)
00147 {
00148   plugin_t* plugin;
00149   policy_t* policy;
00150 
00151   /*
00152    *  Check if the policies have been reduced. If not, then getting
00153    *  the plugins and their arguments is useless; the variables have
00154    *  not been substituted yet.
00155    */
00156   if (!policies_have_been_reduced()) {
00157     lcmaps_log(1, "The policies have not been reduced. Probably the startElevaluationManager has failed or has not been called yet.\n");
00158     return 0;
00159   }
00160 
00161   /*
00162    *  Check if evaluation has been done before, if so use the old
00163    *  results.
00164    */
00165   if (top_plugin)
00166     return top_plugin;
00167 
00168   policy = get_policies();
00169 
00170   while (policy) {
00171     rule_t* rule = policy->rule;
00172 
00173     lcmaps_log_debug(1, "processing policy: %s\n", policy->name);
00174     while (rule) {
00175       lcmaps_log_debug(1, "  processing rule: %s -> %s | %s\n", rule->state, rule->true_branch, rule->false_branch);
00176 
00177       lcmaps_log_debug(1, "  get_plugins:  initializing...\n");
00178       init_name_args(&plugin, rule, STATE);
00179       init_name_args(&plugin, rule, TRUE_BRANCH);
00180       init_name_args(&plugin, rule, FALSE_BRANCH);
00181       lcmaps_log_debug(1, "  get_plugins:  initializing done.\n");
00182 
00183       rule = rule->next;
00184     }
00185     policy = policy->next;
00186   }
00187   
00188   return top_plugin;
00189 }
00190 
00191 
00199 BOOL plugin_exists(const char* string)
00200 {
00201   int space, remainder;
00202   plugin_t *plugin;
00203 
00204   space     = find_first_space(string);
00205   remainder = strlen(string) - space - 1;
00206   plugin    = top_plugin;
00207 
00208   while (plugin) {
00209     if (plugin->name && strncmp(plugin->name, string, space)==0) {
00210       if (plugin->args)
00211         if (strncmp(plugin->args, string+space+1, remainder)!=0) {
00212           plugin = plugin->next;
00213           continue;
00214         }
00215       return TRUE;
00216     }
00217     plugin = plugin->next;
00218   }
00219   
00220   return FALSE;
00221 }
00222 
00223 
00227 void init_name_args(plugin_t** plugin, const rule_t* rule, rule_type_t type)
00228 {
00229   int space, remainder;
00230   const char* string;
00231 
00232   switch (type) {
00233   case STATE:
00234     string = rule->state;
00235     break;
00236   case TRUE_BRANCH:
00237     string = rule->true_branch;
00238     break;
00239   case FALSE_BRANCH:
00240     string = rule->false_branch;
00241     break;
00242   default:
00243     warning(PDL_ERROR, "init_name_args: unknown type!");
00244     return;
00245   }
00246 
00247   lcmaps_log_debug(1, "  init_name_args: processing: %s\n", string);
00248 
00249   if (!string || plugin_exists(string)) {
00250     lcmaps_log_debug(1, "  init_name_args: Either the plugin exists or string == 0.\n");
00251     return;
00252   }
00253 
00254   lcmaps_log_debug(1, "  init_name_args: plugin does not exists.\n");
00255 
00256   if (!top_plugin) {
00257     top_plugin = (plugin_t*)malloc(sizeof(plugin_t));
00258     *plugin = top_plugin;
00259   }
00260   else {
00261     (*plugin)->next = (plugin_t*)malloc(sizeof(plugin_t));
00262     *plugin = (*plugin)->next;
00263   }
00264 
00265   (*plugin)->name = (*plugin)->args = 0;
00266   (*plugin)->next = 0;
00267 
00268   space = find_first_space(string);
00269 
00270   lcmaps_log_debug(1, "  init_name_args: space found a pos: %d  strlen = %d.\n", space, strlen(string));
00271 
00272   (*plugin)->name = (char *)malloc(space+1);
00273   strncpy((*plugin)->name, string, space);
00274   *((*plugin)->name+space) = '\0';
00275   
00276   remainder = strlen(string)-space-1;
00277   if (remainder > 0) {
00278     (*plugin)->args   = (char *)malloc(remainder+1);
00279     strncpy((*plugin)->args, string+space+1, remainder);
00280     *((*plugin)->args+remainder) = '\0';
00281   } else
00282     (*plugin)->args = 0;
00283 
00284   (*plugin)->lineno = rule->lineno;
00285   (*plugin)->next   = 0;
00286 
00287   lcmaps_log_debug(1, "  init_name_args: plugin->name = %s\n", (*plugin)->name);
00288   lcmaps_log_debug(1, "  init_name_args: plugin->args = %s\n", (*plugin)->args);
00289 }
00290 
00291 
00301 int find_first_space(const char* string)
00302 {
00303   int space, max_length;
00304   space = 0;
00305   max_length = strlen(string);
00306 
00307   for (; *string++ != ' ' && space < max_length; ++space);
00308 
00309   return space;
00310 }
00311 
00312 
00318 const char *pdl_path(void)
00319 {
00320   return path;
00321 };
00322 
00323 
00331 int yyerror(const char* s)
00332 {
00333   //  lcmaps_log_debug(1, "%s\n", token_name());
00334 
00335   warning(PDL_ERROR, s);
00336 
00337   return 0;
00338 }
00339 
00340 
00348 void set_path(record_t* path)
00349 {
00350   _set_path(path);
00351 
00352   free(path->string);
00353   free(path);
00354 }
00355 
00356 
00365 void _set_path(const record_t* _path)
00366 {
00367   //  lcmaps_log_debug(1, "set_path: '%s'.\n", _path);
00368 
00369   if (!default_path) {
00370     warning(PDL_ERROR, "path already defined in: %d; ignoring this instance.", path_lineno);
00371     return;
00372   }
00373 
00374   default_path = FALSE;
00375   path_lineno  = _path->lineno;
00376   path         = strdup(_path->string);
00377 }
00378 
00379 
00380 
00384 void free_path(void)
00385 {
00386   if (!default_path && path) {
00387     free((char*)path);
00388     default_path = TRUE;
00389     path = 0;
00390   }
00391 }
00392 
00393 
00394 
00405 record_t* concat_strings(record_t* s1, record_t* s2)
00406 {
00407   record_t* r = _concat_strings(s1, s2, 0);
00408 
00409   free(s1->string);
00410   free(s2->string);
00411   free(s1);
00412   free(s2);
00413 
00414   return r;
00415 }
00416 
00417 
00426 record_t* _concat_strings(const record_t* s1, const record_t* s2,
00427                           const char* extra)
00428 {
00429   int len       = strlen(s1->string);
00430   int len_extra = extra ? strlen(extra) : 0;
00431 
00432   record_t* record = (record_t *)malloc(sizeof(record_t));
00433 
00434   if (!(record->string = (char *)malloc(len + len_extra + strlen(s2->string)+1))) {
00435     warning(PDL_ERROR, "out of memory");
00436     return 0;
00437   }
00438 
00439   strcpy(record->string, s1->string);
00440   if (extra)
00441     strcpy(record->string+len, extra);
00442   strcpy(record->string+len+len_extra, s2->string);
00443 
00444   //lcmaps_log_debug(1, "concat_strings: '%s' + '%s' = '%s'.\n", s1, s2, s3);
00445 
00446   return record;
00447 }
00448 
00449 
00460 record_t* concat_strings_with_space(record_t* s1, record_t* s2)
00461 {
00462   record_t* r;
00463 
00464   /*  Check if there is a string to add.  */
00465   if (strlen(s2->string)!=0) {
00466     /*
00467      *  When the first and second string end with ", do not an extra
00468      *  space. This is the result of an sequence of escaped ".
00469      */
00470     if ((s1->string[strlen(s1->string)-1]=='"') &&
00471         (s2->string[strlen(s2->string)-1]=='"'))
00472       r = _concat_strings(s1, s2, 0);
00473     else
00474       r = _concat_strings(s1, s2, " ");
00475 
00476     free(s1->string);
00477     free(s2->string);
00478     free(s1);
00479     free(s2);
00480   } else {
00481     /*
00482      *  Since there is nothing to concatenate, we simply copy the
00483      *  first string (s1) to the result.
00484      */
00485     r = (record_t*)malloc(sizeof(r));
00486     memcpy(r, s1, sizeof(r));
00487   }
00488 
00489   return r;
00490 }
00491 
00492 
00510 const char* pdl_next_plugin(plugin_status_t status)
00511 {
00512   char* string      = 0;
00513   const char* state = 0;
00514 
00515   switch (status) {
00516   case EVALUATION_START:
00517     /*  Make sure that there is a policy list.  */
00518     if (!(current_policy = get_policies()))
00519       return 0;
00520     if (!(current_rule = current_policy->rule))
00521       return 0;
00522 
00523     state = current_rule->state;
00524     break;
00525 
00526   case EVALUATION_SUCCESS:
00527     if (current_rule)
00528       state = current_rule->true_branch;
00529 
00530     if (current_policy && state)
00531       current_rule = find_state(current_policy->rule, state);
00532     else
00533       current_rule = 0;
00534     break;
00535 
00536   case EVALUATION_FAILURE:
00537     /*
00538      *  Find the next rule for evalaution. The plugins specified by
00539      *  that rule will not be returned by this iterating of the
00540      *  function. Instead the static/global variables are setup, such
00541      *  that on the next iteration the next plugin is returned. Only
00542      *  after the evaluation of the plugin found during this iteration
00543      *  can a decision be made which plugin to return.
00544      *
00545      *  When the last rule has been evaluated, there is the
00546      *  possibility that there is another policy in the configration.
00547      *  Instead of stopping at the end of a rule chain, setup the
00548      *  variables for the next policy rule.
00549      *
00550      */
00551     if (current_rule)
00552       state = current_rule->false_branch;
00553 
00554     /* 
00555      *  Check if either there is a current_rule or a state. If so, we
00556      *  can continue. If there is no current rule, there might be a
00557      *  next policy. This needs to be evaluated next. If there is no
00558      *  state, this is because the false branch does not exist and
00559      *  hence we need to evaluate possible next policies.
00560      *
00561      */
00562     if (!(current_rule && state)) {
00563       if (current_policy && (current_policy = current_policy->next)) {
00564         if ((current_rule = current_policy->rule)) {
00565           int rc;
00566           state = current_rule->state;
00567           lcmaps_log_debug(1, "evaluationmanager: Resetting credential data for policy: %s\n", current_policy->name);
00568           rc = resetCredentialData();
00569           
00570           if (rc) {
00571             warning(PDL_ERROR, "Resetting credential data failed: rc = %d", rc);
00572             return 0;
00573           }
00574         }
00575       }
00576     } else {
00577        /*  We have a valid next state. Let's find the next rule.  */
00578       if (current_policy)
00579         current_rule = find_state(current_policy->rule, state);
00580     }
00581 
00582     break;
00583   }
00584 
00585   /*
00586    *  Create the full plugin name, i.e. including the path. The rules
00587    *  do not specify the path, this must be added so that a single
00588    *  string can be returned. State holde the current plugin name.
00589    *
00590    */
00591   if (state) {
00592     const char* tmp;
00593     int state_length, path_length;
00594 
00595     tmp = state;
00596     state_length = path_length = 0;
00597 
00598     while (*tmp!=' ' && *tmp++!='\0') {
00599       ++state_length;
00600     }
00601     path_length = strlen(pdl_path());
00602 
00603     /*  Allocate memory and initialize the string.  */
00604     string = (char*)malloc(state_length + path_length + 2);
00605     strcpy(string, pdl_path());
00606 
00607     /*  Make sure the path ends in '/'.  */
00608     if (string[path_length-1] != '/')
00609       string[path_length++] = '/';
00610     strncpy(string + path_length, state, state_length);
00611     string[path_length + state_length] = '\0';
00612   }
00613 
00614   return string;
00615 }
00616 
00617 
00622 void free_resources(void)
00623 {
00624   if (script_name) {
00625     free((char*)script_name);
00626     script_name = 0;
00627   }
00628 
00629   free_path();
00630 
00631   free_variables();
00632   free_policies();
00633 
00634   /*
00635    *  YACC takes its input from the stdin by default. When the input
00636    *  is taken from a file, the yyin variable will have a different
00637    *  value from stdin and stderr. If so, it is necessary to close it.
00638    */
00639   if (yyin!=stdin && yyin!=stderr) {
00640     fclose(yyin);
00641     yyin=stdin;
00642   }
00643 
00644 #ifdef HAVE_FLEX
00645   delete_lex_buffer();
00646 #endif
00647 }
00648 
00649 
00658 void warning(pdl_error_t error, const char* s, ...)
00659 {
00660   static char* level = 0;
00661   char buf[2048];
00662   int res;
00663 
00664   va_list args;
00665 
00666   if (error == PDL_ERROR)
00667     parse_error = TRUE;
00668 
00669   if (!level)
00670     level = level_str[PDL_UNKNOWN];
00671 
00672   if (error != PDL_SAME)
00673     level = level_str[error];
00674 
00675   /*
00676    *  Prepend a standard text before the message. This makes reading
00677    *  the errors/warnings a little easier.
00678    */
00679   res = sprintf(buf, "%s:%d: [%s] ", script_name, lineno, level);
00680 
00681   /*  Print (format) the actual message.  */
00682   va_start(args, s);
00683   res += vsnprintf(buf+res, sizeof(buf)-res-2, s, args);
00684   va_end(args);
00685 
00686   /*
00687    *  The string needs to end in a new line and of course strings are
00688    *  termintated by the end of string character. Make sure it happens
00689    *  and respect the buffer size!
00690    */
00691   buf[res<sizeof(buf)-1 ? res++ : sizeof(buf)-2] = '\n';
00692   buf[res<sizeof(buf)   ? res   : sizeof(buf)-1] = '\0';
00693 
00694   lcmaps_log(0, buf);
00695 }
00696 

Generated on Sat Oct 2 02:18:27 2004 for edg-lcmaps by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002