Source File er/er_macro.c

    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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  | }