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