Source File modules/er/er_macro.c

    1    | /***************************************
    2    |   $Revision: 1.5 $
    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   | #include "sk.h"
    35   | #include "er_macro.h"
    36   | #include "er_paths.h"
    37   | #include "er_yacc_helper.h"
    38   | #include "memwrap.h"
    39   |
    40   | #include "ca_configFns.h"
    41   | #include "ca_dictSyms.h"
    42   | #include "ca_macros.h"
    43   |
    44   | GHashTable *er_macro_hash = NULL;
    45   |
    46   | /* process a macro call, i.e. execute one of the predefined macros
    47   |    selected by the 0th argument, using other arguments.
    48   |
    49   |    Uses the er_macro_array[] to find the macro definition.
    50   |
    51   |    Allocates the result string and stores the pointer to it in **output.
    52   |
    53   |    returns 0 on success, non-0 on failure.
    54   | */
    55   |
    56   | int
    57   | ER_process_split(int argc, char **argv, char **output)
    58   | {
    59   |   char *pattern, *ch;
    60   |   GString *result = g_string_new("");
    61   |
    62   |   dieif( argc == 0 ); /* may not be called without the macro name */
    63   |
    64   |   /* find macro, error if not found */
    65   |   if( (pattern = g_hash_table_lookup(er_macro_hash, argv[0])) == NULL ) {
    66   |     return -1;
    67   |   }
    68   |
    69   |   /* copy the macro definition by portions, substituting the $([0-9])
    70   |      entries with arguments. Error if not enough arguments.
    71   |   */
    72   |   do {
    73   |
    74   |     if( (ch = strstr( pattern, "$(" )) == NULL ) {
    75   |       /* no more entries. copy the rest */
    76   |       g_string_append ( result, pattern );
    77   |       break;
    78   |     }
    79   |     else {
    80   |       /* pass the string between here and ch */
    81   |       while( pattern != ch ) {
    82   | 	g_string_append_c ( result, *pattern );
    83   | 	pattern++;
    84   |       }
    85   |       /* check the next 3 characters exist, break the look if not */
    86   |       if( *(ch+2) == '\0' ||  *(ch+3) == '\0') {
    87   | 	break;
    88   |       }
    89   |
    90   |       /* look for the digit and ")", pass the $( through if not present */
    91   |       if( ! isdigit(*(ch+2)) || *(ch+3) != ')' ) {
    92   | 	/* not need to do anything to make it pass through */
    93   | 	;
    94   |       }
    95   |       else {
    96   | 	/* substitute the $(?) with the appropriate argument.
    97   | 	   error if not enough arguments or $(0) is used.*/
    98   | 	int a = *(ch+2) - '0';
    99   |
    100  | 	if( argc < a || a==0) {
    101  | 	  return -1;
    102  | 	}
    103  | 	g_string_append( result, argv[a]);
    104  | 	/* advance the pattern pointer */
    105  | 	pattern += strlen("$(1)");
    106  |       }
    107  |     }
    108  |   } while(1);
    109  |
    110  |   /* copy the pointer, free the orig structure, keep the text */
    111  |
    112  |   *output = (result->str);
    113  |
    114  |   g_string_free( result, FALSE );
    115  |
    116  |   return 0;
    117  | }
    118  |
    119  |
    120  | /* wrapper around the above that splits the string into argv
    121  |    and calls the ER_parse.
    122  |
    123  |    sets the errbuf to the ER_parse_spec result
    124  |
    125  |    returns 0 on success, non-0 on failure.
    126  | */
    127  | int
    128  | ER_macro_spec(char *input, char **errbuf)
    129  | {
    130  |   char **argv = g_strsplit(input, " ", 0);
    131  |   int argc = 0, ret;
    132  |   char *fullspec;
    133  |
    134  |   while( argv[argc] != NULL ) {
    135  |     argc++;
    136  |   }
    137  |
    138  |
    139  |   if( ER_process_split(argc, argv, &fullspec) != 0 ) {
    140  |     /* macro unknown. That's OK, just parse that text now */
    141  |
    142  |     fullspec = strdup(input);
    143  |   }
    144  |
    145  |   ret = ER_parse_spec(fullspec, errbuf);
    146  |
    147  |   free(fullspec);
    148  |   g_strfreev(argv);
    149  |   return ret;
    150  |
    151  | }
    152  |
    153  |
    154  | void
    155  | ER_make_macro(char *name, char *def)
    156  | {
    157  |   char *cp_name = wr_string(name);
    158  |   char *cp_def  = wr_string(def);
    159  |
    160  |   void *oldkey, *oldval;
    161  |
    162  |   /* cleanup on redefinition */
    163  |   if( g_hash_table_lookup_extended(er_macro_hash, name,
    164  | 				   &oldkey, &oldval) == TRUE ) {
    165  |     g_hash_table_remove(er_macro_hash, name);
    166  |     wr_free(oldkey);
    167  |     wr_free(oldval);
    168  |   }
    169  |
    170  |   g_hash_table_insert(er_macro_hash, cp_name, cp_def);
    171  | }
    172  |
    173  |
    174  | /* predefine some macros */
    175  | void
    176  | ER_macro_predef(void)
    177  | {
    178  |   /* create the hash with hashing and equality testing functions
    179  |      specific for strings
    180  |   */
    181  |   er_macro_hash = g_hash_table_new(g_str_hash, g_str_equal);
    182  |
    183  | #define DBUPDLOG_FORMAT "  FORMAT SEVCHAR|FACSYMB|TEXTLONG|DATETIME|PIDFULL|PROGNAME|MNEMONIC  "
    184  | #define RIPLOG_FORMAT   "  FORMAT SEVCHAR|FACSYMB|TEXTLONG|DATETIME|PIDFULL|PROGNAME|THR_ID|MNEMONIC  "
    185  |
    186  |   /* catch-all for dbupdate */
    187  |   ER_make_macro("DBUPERR", "CREATE dbuperr {"
    188  | 		DBUPDLOG_FORMAT "NAME $(1) DATE}"
    189  | 		" ( FAC MM|UP SEV W- )");
    190  |
    191  |   /* catch-all for rip */
    192  |   ER_make_macro("ALLRIPERR", "CREATE allriperr { "
    193  | 		RIPLOG_FORMAT "NAME $(1) DATE}"
    194  | 		" (FAC ALL SEV W- )");
    195  |
    196  |   /* selected: errors in ripupdate */
    197  |   ER_make_macro("RIPUPERR", "CREATE ripuperr {"
    198  | 		RIPLOG_FORMAT "NAME $(1) DATE}"
    199  | 		" (FAC UD SEV W- )");
    200  |
    201  |   /* querylog: logs all rip queries */
    202  |   ER_make_macro("QRYLOG", "CREATE qrylog {"
    203  | 		RIPLOG_FORMAT "NAME $(1) DATE}"
    204  | 		" (FAC PW ASP PW_I_QRYLOG SEV I )");
    205  |
    206  |   /* audit: any security related messages from RIP */
    207  |   ER_make_macro("RIPAUDIT", "CREATE ripaudit {"
    208  | 		RIPLOG_FORMAT "NAME $(1) DATE}"
    209  | 		"( FAC PW ASP PW_I_PASSUN SEV i )"
    210  | 		" (  FAC AC ASP AC_I_PERMBAN SEV I )");
    211  |
    212  |   /* ripupdlog: logs all update transactions */
    213  |   ER_make_macro("RIPUPDLOG", "CREATE ripupdlog_$(2) {"
    214  | 		RIPLOG_FORMAT "NAME $(1)_$(2) DATE}"
    215  | 		" ( FAC UD ASP 0xffffffff SEV I THR self)");
    216  |
    217  |   /* ripmirlog */
    218  |   ER_make_macro("RIPMIRLOG", "CREATE ripmirlog {"
    219  | 		RIPLOG_FORMAT "NAME $(1) DATE }"
    220  | 		"( FAC PM ASP 0xffffffff SEV I )");
    221  |
    222  |   /* server log: all administration by SV (startup, shutdown, etc) and errors */
    223  |   ER_make_macro("RIPSVRLOG", "CREATE ripsvrlog {"
    224  | 		RIPLOG_FORMAT "NAME $(1) DATE}"
    225  | 		" ( FAC SV ASP 0xffffffff SEV I-F )");
    226  |   /* dbase log: all errors of SQ */
    227  |   ER_make_macro("SQLOG", " CREATE sqlog {"
    228  | 		RIPLOG_FORMAT "NAME $(1) DATE}"
    229  | 		" ( FAC SQ SEV W- )");
    230  |
    231  | }
    232  |
    233  | static
    234  | void er_macro_list_hook (void* key, void * value, void *condat)
    235  | {
    236  |   SK_cd_printf(condat, "%s: %s\n", (char *) key, (char *) value);
    237  | }
    238  |
    239  | void
    240  | ER_macro_list(sk_conn_st *condat)
    241  | {
    242  |   g_hash_table_foreach(er_macro_hash, er_macro_list_hook, condat );
    243  | }
    244  |
    245  | /* override macros with the definitions from the config file */
    246  | void
    247  | ER_proc_ca_macro(void)
    248  | {
    249  |   char *alldef = ca_get_er_macro ;
    250  |   char *this_line = alldef;
    251  |   char *defname, *defbody, *end_line;
    252  |
    253  |   /* alldef is a copy of the configured value. so we can modify it
    254  |      if it helps us to do it line by line */
    255  |
    256  |   /* ER_MACRO may not be present in the configuration, in which case
    257  |      ca_get_er_macro returns NULL */
    258  |
    259  |   if( alldef != NULL ) {
    260  |
    261  |     while( *this_line != '\0' ) {
    262  |       /* separate the line */
    263  |       end_line = strchr(this_line, '\n');
    264  |       *end_line = '\0';
    265  |
    266  |       /* advance to non-whitespace */
    267  |       while( isspace(*this_line) ) {
    268  | 	this_line++;
    269  |       }
    270  |
    271  |       /* find the name and body of the definition */
    272  |       defname = strsep(&this_line, " \t");
    273  |       defbody = this_line;
    274  |
    275  |       /* fire */
    276  |       dieif( defname == NULL || defbody == NULL );
    277  |       ER_make_macro( defname, defbody );
    278  |
    279  |       this_line = end_line + 1;
    280  |     }
    281  |
    282  |     free(alldef);
    283  |   }
    284  | }
    285  |
    286  |
    287  | /* process the error definitions from the config file */
    288  | void
    289  | ER_proc_ca_err(void)
    290  | {
    291  |   char *alldef = ca_get_er_def ;
    292  |   char *this_line = alldef;
    293  |   char *defname, *defbody, *end_line;
    294  |   char *erret = NULL;
    295  |   int res;
    296  |
    297  |     /* alldef is a copy of the configured value. so we can modify it
    298  |        if it helps us to do it line by line */
    299  |
    300  |   /* ER_DEF may not be present in the configuration, in which case
    301  |      ca_get_er_def returns NULL */
    302  |   if( alldef != NULL ) {
    303  |
    304  |     while( *this_line != '\0' ) {
    305  |       /* separate the line */
    306  |       end_line = strchr(this_line, '\n');
    307  |       *end_line = '\0';
    308  |
    309  |       /* fire */
    310  |       if( (res = ER_macro_spec(this_line, &erret)) != 0 ) {
    311  | 	fputs(erret, stderr);
    312  | 	die;
    313  |       }
    314  |
    315  |       free(erret);
    316  |
    317  |       this_line = end_line + 1;
    318  |     }
    319  |
    320  |     free(alldef);
    321  |   }
    322  | }