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

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