/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
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.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 }