modules/er/er_macro.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. ER_process_split
  2. ER_macro_spec
  3. ER_make_macro
  4. ER_macro_predef
  5. er_macro_list_hook
  6. ER_macro_list
  7. ER_proc_ca_macro
  8. ER_proc_ca_err

   1 /***************************************
   2   $Revision: 1.10 $
   3 
   4   Error reporting (er) er_macro.c - simple macro processor
   5 
   6   Status: NOT REVUED, PARTLY TESTED
   7 
   8   Design and implementation by: Marek Bukowy
   9 
  10   ******************/ /******************
  11   Copyright (c) 1999,2000                             RIPE NCC
  12  
  13   All Rights Reserved
  14   
  15   Permission to use, copy, modify, and distribute this software and its
  16   documentation for any purpose and without fee is hereby granted,
  17   provided that the above copyright notice appear in all copies and that
  18   both that copyright notice and this permission notice appear in
  19   supporting documentation, and that the name of the author not be
  20   used in advertising or publicity pertaining to distribution of the
  21   software without specific, written prior permission.
  22   
  23   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  24   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  25   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  26   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  27   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  28   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29   ***************************************/
  30 
  31 #include <string.h>
  32 #include <glib.h>
  33 #include "stubs.h"
  34 
  35 #include "erroutines.h"
  36 #include "er_yacc_helper.h" 
  37 
  38 #include "memwrap.h"
  39 #include "sk.h"
  40 
  41 #include "ca_configFns.h"
  42 #include "ca_dictionary.h"
  43 #include "ca_macros.h"
  44 
  45 #include "thread.h" /*rwlock*/
  46 
  47 #include "er_macro.h"
  48 
  49 #include "ut_string.h"
  50 
  51 
  52 /*++++++++++++++++++++++++++++++++++++++
  53   
  54   processes a macro call, i.e. executes one of the predefined macros
  55   selected by the 0th word of the array, using other words as
  56   arguments to that macro. Uses the er_macro_array[] to find the
  57   macro definition.  Allocates the result string and stores the
  58   pointer to it in **output.
  59   
  60   int ER_process_split    returns 0 on success, non-0 on failure.
  61 
  62   int argc                number of words in the word array
  63   
  64   char **argv             word array (pointers to strings)
  65   
  66   char **output           storage for the result pointer (to allocated text)
  67   ++++++++++++++++++++++++++++++++++++++*/
  68 int
  69 ER_process_split(int argc, char **argv, char **output)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71   unsigned char *ch;
  72   char *pattern;
  73   GString *result = g_string_new("");
  74   int retval = 0;
  75 
  76   TH_acquire_write_lock( &er_paths_lock );
  77 
  78   if( /* if called without the macro name */
  79      argc == 0  
  80      /* or macro can not be found */
  81      || (pattern = g_hash_table_lookup(er_macro_hash, argv[0])) == NULL ) {
  82 
  83     retval = -1;
  84   }
  85   else {
  86     /* copy the macro definition by portions, substituting the $([0-9]) 
  87        entries with arguments. Error if not enough arguments.
  88     */
  89     do {
  90       
  91       if( (ch = (unsigned char *) strstr( pattern, "$(" )) == NULL ) {
  92         /* no more entries. copy the rest */
  93         g_string_append ( result, pattern );
  94         break;
  95       }
  96       else {
  97         /* pass the string between here and ch */
  98         while( pattern != (char *)ch ) {
  99           g_string_append_c ( result, *pattern );
 100           pattern++;
 101         }
 102         /* check the next 3 characters exist, break the look if not */
 103         if( *(ch+2) == '\0' ||  *(ch+3) == '\0') {
 104           break;
 105         }
 106 
 107         /* look for the digit and ")", pass the $( through if not present */
 108         if( ! isdigit(*(ch+2)) || *(ch+3) != ')' ) {
 109           /* not need to do anything to make it pass through */
 110           ;
 111         }
 112         else {
 113           /* substitute the $(?) with the appropriate argument.
 114              error if not enough arguments or $(0) is used.*/
 115           int a = *(ch+2) - '0';
 116         
 117           if( argc < a || a==0) {
 118             retval = -1;
 119             break;
 120           }
 121           g_string_append( result, argv[a]);
 122           /* advance the pattern pointer */
 123           pattern += strlen("$(1)");
 124         }
 125       }
 126     } while(1);
 127   }
 128 
 129   /* copy the pointer, free the orig structure, keep the text */
 130     
 131   *output = (result->str); 
 132   
 133   g_string_free( result, FALSE );
 134 
 135   TH_release_write_lock( &er_paths_lock );
 136 
 137   return retval;
 138 }
 139 
 140 
 141 /*++++++++++++++++++++++++++++++++++++++
 142   
 143   Take a text line and parse it as an error specification
 144   line. Optionally, if the first word is a macro, run the macro using
 145   other words as its arguments.  This is basically a wrapper around
 146   ER_process_split() that splits the string into argv and calls the
 147   ER_parse.
 148 
 149   sets the errbuf to the result of ER_parse_spec.
 150 
 151   int ER_macro_spec      returns 0 on success, non-0 on failure.  
 152 
 153   char *input            input line
 154 
 155   char **errbuf          storage for the result pointer (to allocated text)
 156   ++++++++++++++++++++++++++++++++++++++*/
 157 int
 158 ER_macro_spec(char *input, char **errbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 159 {
 160   char *copy = ut_string_compress(input);
 161   char **argv = g_strsplit(copy, " ", 0);
 162   int argc = 0, ret;
 163   char *fullspec;
 164 
 165   while( argv[argc] != NULL ) {
 166     argc++;
 167   }
 168   
 169 
 170   if( ER_process_split(argc, argv, &fullspec) != 0 ) {
 171     /* macro unknown. That's OK, just parse that text now */
 172 
 173     fullspec = strdup(input);
 174   }
 175 
 176   ret = ER_parse_spec(fullspec, errbuf);
 177 
 178   free(fullspec);
 179   free(copy);
 180   g_strfreev(argv);
 181 
 182   return ret;
 183   
 184 }
 185 
 186 
 187 /*++++++++++++++++++++++++++++++++++++++
 188   (Re)Define a macro.
 189   
 190   char *name     macro name
 191   
 192   char *def      macro contents
 193   ++++++++++++++++++++++++++++++++++++++*/
 194 void
 195 ER_make_macro(char *name, char *def)
     /* [<][>][^][v][top][bottom][index][help] */
 196 {
 197   char *cp_name = wr_string(name);
 198   char *cp_def  = wr_string(def);
 199 
 200   void *oldkey, *oldval;
 201 
 202   TH_acquire_write_lock( &er_paths_lock );
 203 
 204   /* cleanup on redefinition */
 205   if( g_hash_table_lookup_extended(er_macro_hash, name, 
 206                                    &oldkey, &oldval) == TRUE ) {
 207     g_hash_table_remove(er_macro_hash, name);
 208     wr_free(oldkey);
 209     wr_free(oldval);
 210   }
 211   
 212   g_hash_table_insert(er_macro_hash, cp_name, cp_def);
 213 
 214   TH_release_write_lock( &er_paths_lock );
 215 }
 216 
 217 
 218 /*++++++++++++++++++++++++++++++++++++++
 219   
 220   predefine some macros useful for the whois_rip server.
 221   XXX - this should not be here, it should be done via the CA module!
 222 
 223   ++++++++++++++++++++++++++++++++++++++*/
 224 void
 225 ER_macro_predef(void)
     /* [<][>][^][v][top][bottom][index][help] */
 226 {
 227 
 228 #define DBUPDLOG_FORMAT "  FORMAT SEVCHAR|FACSYMB|TEXTLONG|DATETIME|PIDFULL|PROGNAME|MNEMONIC  "
 229 #define RIPLOG_FORMAT   "  FORMAT SEVCHAR|FACSYMB|TEXTLONG|DATETIME|PIDFULL|PROGNAME|THR_ID|MNEMONIC  "
 230 
 231   /* catch-all for dbupdate */
 232   ER_make_macro("DBUPERR", "CREATE dbuperr {"
 233                 DBUPDLOG_FORMAT "NAME '$(1)' DATE}"
 234                 " ( FAC MM|UP SEV W- )");
 235 
 236   /* catch-all for rip */
 237   ER_make_macro("ALLRIPERR", "CREATE allriperr { " 
 238                 RIPLOG_FORMAT "NAME '$(1)' DATE}" 
 239                 " (FAC ALL SEV W- )");
 240 
 241   /* selected: errors in ripupdate */
 242   ER_make_macro("RIPUPERR", "CREATE ripuperr {" 
 243                 RIPLOG_FORMAT "NAME '$(1)' DATE}" 
 244                 " (FAC UD SEV W- )");
 245 
 246   /* querylog: logs all rip queries */
 247   ER_make_macro("QRYLOG", "CREATE qrylog {" 
 248                 RIPLOG_FORMAT "NAME '$(1)' DATE}" 
 249                 " (FAC PW ASP PW_I_QRYLOG SEV I )");
 250 
 251   /* audit: any security related messages from RIP */
 252   ER_make_macro("RIPAUDIT", "CREATE ripaudit {"
 253                 RIPLOG_FORMAT "NAME '$(1)' DATE}"
 254                 "( FAC PW ASP PW_I_PASSUN SEV i )" 
 255                 " (  FAC AC ASP AC_I_PERMBAN SEV I )");
 256 
 257   /* ripupdlog: logs all update transactions */
 258   ER_make_macro("RIPUPDLOG", "CREATE 'ripupdlog_$(2)' {" 
 259                 RIPLOG_FORMAT "NAME '$(1)_$(2)' DATE}" 
 260                 " ( FAC UD ASP 0xffffffff SEV I THR self)");
 261 
 262   /* ripmirlog */
 263   ER_make_macro("RIPMIRLOG", "CREATE ripmirlog {"  
 264                 RIPLOG_FORMAT "NAME '$(1)' DATE }"
 265                 "( FAC PM ASP 0xffffffff SEV I )");
 266 
 267   /* server log: all administration by SV (startup, shutdown, etc) and errors */
 268   ER_make_macro("RIPSVRLOG", "CREATE ripsvrlog {" 
 269                 RIPLOG_FORMAT "NAME '$(1)' DATE}" 
 270                 " ( FAC SV ASP 0xffffffff SEV I-F )");                                                                                        
 271   /* dbase log: all errors of SQ */
 272   ER_make_macro("SQLOG", " CREATE sqlog {" 
 273                 RIPLOG_FORMAT "NAME '$(1)' DATE}" 
 274                 " ( FAC SQ SEV W- )");
 275   
 276 }
 277 
 278 
 279 /*++++++++++++++++++++++++++++++++++++++
 280   
 281   Prints the arguments (key and value of a hash) to the given
 282   connection (used for listing the defined macros)
 283 
 284   void * key       hash key
 285 
 286   void * value     hash value
 287 
 288   void *condat     connection data structure
 289   ++++++++++++++++++++++++++++++++++++++*/
 290 static
 291 void er_macro_list_hook (void* key, void * value, void *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 292 {
 293   SK_cd_printf(condat, "%s: %s\n", (char *) key, (char *) value);
 294 }
 295      
 296 
 297 
 298 /*++++++++++++++++++++++++++++++++++++++
 299   
 300   Lists all currently defined macros to the given connection.
 301 
 302   sk_conn_st *condat  connection data structure
 303   ++++++++++++++++++++++++++++++++++++++*/
 304 void 
 305 ER_macro_list(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 306 {
 307   TH_acquire_read_lock( &er_paths_lock );
 308   g_hash_table_foreach(er_macro_hash, er_macro_list_hook, condat );
 309   TH_release_read_lock( &er_paths_lock );
 310 }
 311 
 312 
 313 
 314 /*++++++++++++++++++++++++++++++++++++++
 315 
 316  Defines the macros with the definitions from the config file,
 317  overriding any currently defined ones if the same name is used.
 318  
 319  ++++++++++++++++++++++++++++++++++++++*/
 320 void 
 321 ER_proc_ca_macro(void)
     /* [<][>][^][v][top][bottom][index][help] */
 322 {
 323   char *alldef = ca_get_er_macro ;
 324   char *this_line = alldef;
 325   char *defname, *defbody, *end_line;
 326   
 327   /* alldef is a copy of the configured value. so we can modify it
 328      if it helps us to do it line by line */
 329   
 330   /* ER_MACRO may not be present in the configuration, in which case 
 331      ca_get_er_macro returns NULL */
 332 
 333   if( alldef != NULL ) {
 334     
 335     while( *this_line != '\0' ) {
 336       /* separate the line */
 337       end_line = strchr(this_line, '\n');
 338       *end_line = '\0';
 339       
 340       /* advance to non-whitespace */
 341       while( isspace(* (unsigned char*) this_line) ) {
 342         this_line++;
 343       }
 344       
 345       /* find the name and body of the definition */
 346       defname = strsep(&this_line, " \t");
 347       defbody = this_line;
 348       
 349       /* fire */
 350       dieif( defname == NULL || defbody == NULL );
 351       ER_make_macro( defname, defbody );
 352       
 353       this_line = end_line + 1;
 354     }
 355     
 356     free(alldef);
 357   } 
 358   
 359 }
 360 
 361 
 362 /*++++++++++++++++++++++++++++++++++++++
 363   
 364   Processes the error definitions from the config file. The
 365   definitions can be specified with the use of a macro or without.
 366   
 367   ++++++++++++++++++++++++++++++++++++++*/
 368 void 
 369 ER_proc_ca_err(void)
     /* [<][>][^][v][top][bottom][index][help] */
 370 {
 371   char *alldef = ca_get_er_def ;
 372   char *this_line = alldef;
 373   char *end_line;
 374   char *erret = NULL;
 375   int res;
 376  
 377     /* alldef is a copy of the configured value. so we can modify it
 378        if it helps us to do it line by line */
 379 
 380   /* ER_DEF may not be present in the configuration, in which case 
 381      ca_get_er_def returns NULL */
 382   if( alldef != NULL ) {
 383     
 384     while( *this_line != '\0' ) {
 385       /* separate the line */
 386       end_line = strchr(this_line, '\n');
 387       *end_line = '\0';
 388       
 389       /* fire */      
 390       if( (res = ER_macro_spec(this_line, &erret)) != 0 ) {
 391         fputs(erret, stderr);
 392         die;
 393       }
 394       
 395       free(erret); 
 396       
 397       this_line = end_line + 1;
 398     }
 399     
 400     free(alldef);
 401   }
 402 }

/* [<][>][^][v][top][bottom][index][help] */