## 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] */