modules/er/er_macro.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- ER_process_split
- ER_macro_spec
- ER_make_macro
- ER_macro_predef
- er_macro_list_hook
- ER_macro_list
- ER_proc_ca_macro
- 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 }