summaryrefslogtreecommitdiffstatsabout
path: root/utility/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'utility/config.c')
-rw-r--r--utility/config.c263
1 files changed, 190 insertions, 73 deletions
diff --git a/utility/config.c b/utility/config.c
index 6b3dce1..847d474 100644
--- a/utility/config.c
+++ b/utility/config.c
@@ -3,53 +3,61 @@
3#include "apr_file_io.h" 3#include "apr_file_io.h"
4#include "apr_strings.h" 4#include "apr_strings.h"
5#include "apr_hash.h" 5#include "apr_hash.h"
6#include "apr_lib.h" 6
7#include "shell.h" 7#include "shell.h"
8#include "config.h" 8#include "config.h"
9#include "util.h"
10#include "logparse.h"
9 11
10apr_hash_t *g_config_opts; 12apr_hash_t *g_config_opts;
11 13
12apr_status_t config_set_string(config_t *cfg, config_opt_t *opt, int argc, 14static apr_status_t config_set_string(config_t *cfg, config_opt_t *opt,
13 const char **argv) 15 int argc, const char **argv)
14{ 16{
15 int offset = (int)(long)opt->data; 17 int offset = (int)(long)opt->data;
16 char **data = (char **)((void *)cfg + offset); 18 char **data = (char **)((void *)cfg + offset);
17 if (argc != 2) return APR_EINVAL; 19 if (argc != 2)
20 return APR_EINVAL;
18 *data = apr_pstrdup(cfg->pool, argv[1]); 21 *data = apr_pstrdup(cfg->pool, argv[1]);
19 return APR_SUCCESS; 22 return APR_SUCCESS;
20} 23}
21 24
22apr_status_t config_set_int(config_t *cfg, config_opt_t *opt, int argc, 25static apr_status_t config_set_int(config_t *cfg, config_opt_t *opt, int argc,
26 const char **argv) __attribute__ ((__unused__));
27static apr_status_t config_set_int(config_t *cfg, config_opt_t *opt, int argc,
23 const char **argv) 28 const char **argv)
24{ 29{
25 int offset = (int)(long)opt->data; 30 int offset = (int)(long)opt->data;
26 int *data = (int *)((void *)cfg + offset); 31 int *data = (int *)((void *)cfg + offset);
27 if (argc != 2) return APR_EINVAL; 32 if (argc != 2)
33 return APR_EINVAL;
28 *data = apr_atoi64(argv[1]); 34 *data = apr_atoi64(argv[1]);
29 return APR_SUCCESS; 35 return APR_SUCCESS;
30} 36}
31 37
32apr_status_t config_set_flag(config_t *cfg, config_opt_t *opt, int argc, 38static apr_status_t config_set_flag(config_t *cfg, config_opt_t *opt, int argc,
33 const char **argv) 39 const char **argv)
34{ 40{
35 int offset = (int)(long)opt->data; 41 int offset = (int)(long)opt->data;
36 int *data = (int *)((void *)cfg + offset); 42 int *data = (int *)((void *)cfg + offset);
37 if (argc != 2) return APR_EINVAL; 43 if (argc != 2)
44 return APR_EINVAL;
38 *data = CHECK_YESNO(argv[1]); 45 *data = CHECK_YESNO(argv[1]);
39 return APR_SUCCESS; 46 return APR_SUCCESS;
40} 47}
41 48
42apr_status_t config_set_loglevel(config_t *cfg, config_opt_t *opt, int argc, 49static apr_status_t config_set_loglevel(config_t *cfg, config_opt_t *opt,
43 const char **argv) 50 int argc, const char **argv)
44{ 51{
45 if (argc != 2) return APR_EINVAL; 52 if (argc != 2)
46 if (!strcasecmp(argv[1],"error")) { 53 return APR_EINVAL;
54 if (!strcasecmp(argv[1], "error")) {
47 cfg->loglevel = LOGLEVEL_ERROR; 55 cfg->loglevel = LOGLEVEL_ERROR;
48 } else if (!strcasecmp(argv[1],"warn")) { 56 } else if (!strcasecmp(argv[1], "warn")) {
49 cfg->loglevel = LOGLEVEL_WARN; 57 cfg->loglevel = LOGLEVEL_WARN;
50 } else if (!strcasecmp(argv[1],"debug")) { 58 } else if (!strcasecmp(argv[1], "debug")) {
51 cfg->loglevel = LOGLEVEL_DEBUG; 59 cfg->loglevel = LOGLEVEL_DEBUG;
52 } else if (!strcasecmp(argv[1],"quiet")) { 60 } else if (!strcasecmp(argv[1], "quiet")) {
53 cfg->loglevel = LOGLEVEL_QUIET; 61 cfg->loglevel = LOGLEVEL_QUIET;
54 } else { 62 } else {
55 cfg->loglevel = LOGLEVEL_ERROR; 63 cfg->loglevel = LOGLEVEL_ERROR;
@@ -57,49 +65,51 @@ apr_status_t config_set_loglevel(config_t *cfg, config_opt_t *opt, int argc,
57 return APR_SUCCESS; 65 return APR_SUCCESS;
58} 66}
59 67
60apr_status_t config_set_dbconnect(config_t *cfg, config_opt_t *opt, int argc, 68static apr_status_t config_set_dbconnect(config_t *cfg, config_opt_t *opt,
61 const char **argv) 69 int argc, const char **argv)
62{ 70{
63 return APR_SUCCESS; 71 return APR_SUCCESS;
64} 72}
65 73
66apr_status_t config_set_dbparam(config_t *cfg, config_opt_t *opt, int argc, 74static apr_status_t config_set_dbparam(config_t *cfg, config_opt_t *opt,
67 const char **argv) 75 int argc, const char **argv)
68{ 76{
69 return APR_SUCCESS; 77 return APR_SUCCESS;
70} 78}
71 79
72apr_status_t config_set_inputfile(config_t *cfg, config_opt_t *opt, int argc, 80static apr_status_t config_set_inputfile(config_t *cfg, config_opt_t *opt,
73 const char **argv) 81 int argc, const char **argv)
74{ 82{
75 char **newp; 83 char **newp;
76 if (argc != 2) return APR_EINVAL; 84 if (argc != 2)
85 return APR_EINVAL;
77 newp = (char **)apr_array_push(cfg->input_files); 86 newp = (char **)apr_array_push(cfg->input_files);
78 *newp = apr_pstrdup(cfg->pool, argv[1]); 87 *newp = apr_pstrdup(cfg->pool, argv[1]);
79 return APR_SUCCESS; 88 return APR_SUCCESS;
80} 89}
81 90
82apr_status_t config_set_dummy(config_t *cfg, config_opt_t *opt, int argc, 91static apr_status_t config_set_dummy(config_t *cfg, config_opt_t *opt,
83 const char **argv) 92 int argc, const char **argv)
84{ 93{
85 return APR_SUCCESS; 94 return APR_SUCCESS;
86} 95}
87 96
88apr_status_t config_set_logformat(config_t *cfg, config_opt_t *opt, int argc, 97static apr_status_t config_set_logformat(config_t *cfg, config_opt_t *opt,
89 const char **argv) 98 int argc, const char **argv)
90{ 99{
91 config_logformat_t *format; 100 config_logformat_t *format;
92 config_logformat_field_t *field; 101 config_logformat_field_t *field;
93 102
94 if (argc != 4) return APR_EINVAL; 103 if (argc != 4)
104 return APR_EINVAL;
95 105
96 format = apr_hash_get(cfg->log_formats,argv[1],APR_HASH_KEY_STRING); 106 format = apr_hash_get(cfg->log_formats, argv[1], APR_HASH_KEY_STRING);
97 if (!format) { 107 if (!format) {
98 format = apr_palloc(cfg->pool, sizeof(config_logformat_t)); 108 format = apr_palloc(cfg->pool, sizeof(config_logformat_t));
99 format->name = apr_pstrdup(cfg->pool, argv[1]); 109 format->name = apr_pstrdup(cfg->pool, argv[1]);
100 format->fields = apr_array_make(cfg->pool, 5, 110 format->fields = apr_array_make(cfg->pool, 5,
101 sizeof(config_logformat_field_t)); 111 sizeof(config_logformat_field_t));
102 apr_hash_set(cfg->log_formats, argv[1], APR_HASH_KEY_STRING, format); 112 apr_hash_set(cfg->log_formats, apr_pstrdup(cfg->pool,argv[1]), APR_HASH_KEY_STRING, format);
103 } 113 }
104 field = (config_logformat_field_t *)apr_array_push(format->fields); 114 field = (config_logformat_field_t *)apr_array_push(format->fields);
105 field->name = apr_pstrdup(cfg->pool, argv[2]); 115 field->name = apr_pstrdup(cfg->pool, argv[2]);
@@ -107,18 +117,100 @@ apr_status_t config_set_logformat(config_t *cfg, config_opt_t *opt, int argc,
107 return APR_SUCCESS; 117 return APR_SUCCESS;
108} 118}
109 119
120static apr_status_t config_set_output_field(config_t *cfg, config_opt_t *opt,
121 int argc, const char **argv)
122{
123 config_output_field_t *field;
124 char *type, *size, *temp;
125
126 if (argc < 4)
127 return APR_EINVAL;
128 field = (config_output_field_t *)apr_array_push(cfg->output_fields);
129 field->field = apr_pstrdup(cfg->pool, argv[1]);
130 field->source = apr_pstrdup(cfg->pool, argv[3]);
131
132 type = size = apr_pstrdup(cfg->pool, argv[2]);
133 while (*size!='\0' && *size!='(')
134 size++;
135 if (*size == '(') {
136 *size = '\0';
137 size++;
138 temp = size;
139 while (*temp != '\0' && *temp != ')')
140 temp++;
141 *temp = '\0';
142 field->size = apr_atoi64(size);
143 }
144 if (strcasecmp("VARCHAR", type)==0) {
145 field->datatype = LOGSQL_DATATYPE_VARCHAR;
146 } else if (strcasecmp("INT", type)==0) {
147 field->datatype = LOGSQL_DATATYPE_INT;
148 } else if (strcasecmp("CHAR", type)==0) {
149 field->datatype = LOGSQL_DATATYPE_CHAR;
150 } else if (strcasecmp("SMALLINT", type)==0) {
151 field->datatype = LOGSQL_DATATYPE_SMALLINT;
152 } else if (strcasecmp("BIGINT", type)==0) {
153 field->datatype = LOGSQL_DATATYPE_BIGINT;
154 } else {
155 return APR_EINVAL;
156 }
157
158 // Has a function
159 if (argc > 4) {
160 int i;
161 field->fname = apr_pstrdup(cfg->pool, argv[4]);
162 field->func = parser_get_func(field->fname);
163 field->args = apr_pcalloc(cfg->pool, sizeof(char *) * (argc-4+1));
164 for (i=5; i<=argc; i++) {
165 field->args[i-5] = apr_pstrdup(cfg->pool, argv[i]);
166 }
167 }
168
169 return APR_SUCCESS;
170}
171
172static apr_status_t config_set_filter(config_t *cfg, config_opt_t *opt,
173 int argc, const char **argv)
174{
175 int argn = 1;
176 config_filter_t *filter;
177 filter = apr_pcalloc(cfg->pool, sizeof(config_filter_t));
178
179 if (opt->name[0]!='L') { // Pre or post 2-3 args
180 if (argc == 1)
181 return APR_EINVAL;
182 filter->field = apr_pstrdup(cfg->pool, argv[1]);
183 argn++;
184 } // Otherwise Line based only 1-2 args (no field)
185 if (argc <= argn)
186 return APR_EINVAL;
187 if (argv[argn][0] == '+')
188 argn++;
189 if (argv[argn][0] == '-') {
190 filter->negative = 1;
191 argn++;
192 }
193 if (argc <= argn)
194 return APR_EINVAL;
195 filter->filter = apr_pstrdup(cfg->pool, argv[argn]);
196 filter->regex = ap_pregcomp(cfg->pool, filter->filter, AP_REG_ICASE);
197 return APR_SUCCESS;
198}
199
110void config_dump(config_t *cfg) 200void config_dump(config_t *cfg)
111{ 201{
112 apr_hash_index_t *hi; 202 apr_hash_index_t *hi;
203 int i;
204 config_output_field_t *fields;
113 205
114 printf("ErrorLog: %s\n",cfg->errorlog); 206 printf("ErrorLog: %s\n", cfg->errorlog);
115 printf("LogLevel: %d\n",cfg->loglevel); 207 printf("LogLevel: %d\n", cfg->loglevel);
116 208
117 printf("InputDir: %s\n",cfg->input_dir); 209 printf("InputDir: %s\n", cfg->input_dir);
118 210
119 printf("Table: %s\n",cfg->table); 211 printf("Table: %s\n", cfg->table);
120 printf("Transactions: %d\n",cfg->transactions); 212 printf("Transactions: %d\n", cfg->transactions);
121 printf("MachineID: %s\n",cfg->machineid); 213 printf("MachineID: %s\n", cfg->machineid);
122 214
123 printf("Log formats:\n"); 215 printf("Log formats:\n");
124 for (hi = apr_hash_first(cfg->pool, cfg->log_formats); hi; hi 216 for (hi = apr_hash_first(cfg->pool, cfg->log_formats); hi; hi
@@ -128,31 +220,39 @@ void config_dump(config_t *cfg)
128 int i; 220 int i;
129 221
130 apr_hash_this(hi, NULL, NULL, (void **)&format); 222 apr_hash_this(hi, NULL, NULL, (void **)&format);
131 printf(">> %s\n",format->name); 223 printf(">> '%s'\n", format->name);
132 fields = (config_logformat_field_t *)format->fields->elts; 224 fields = (config_logformat_field_t *)format->fields->elts;
133 for (i=0; i<format->fields->nelts; i++) { 225 for (i=0; i<format->fields->nelts; i++) {
134 printf(">>>> %s:%s\n", fields[i].name, fields[i].datatype); 226 printf(">>>> %s:%s\n", fields[i].name, fields[i].datatype);
135 } 227 }
136 } 228 }
137 printf("Log Format: %s\n",cfg->logformat); 229 printf("Log Format: '%s'\n", cfg->logformat);
138 230
139 printf("DryRun: %d\n",cfg->dryrun); 231 printf("Output Fields:\n");
140 printf("Summary: %d\n",cfg->summary); 232 fields = (config_output_field_t *)cfg->output_fields->elts;
141} 233 for (i=0; i<cfg->output_fields->nelts; i++) {
142 234 printf(">> %s %s(%d): %s", fields[i].field, logsql_field_datatyeName(fields[i].datatype), fields[i].size, fields[i].source);
143static char *lowerstr(apr_pool_t *pool, const char *input) { 235 if (fields[i].func) {
144 char *temp; 236 printf(" :: %s(", fields[i].fname);
145 char *itr; 237 if (fields[i].args) {
146 temp = apr_pstrdup(pool, input); 238 int a = 0;
147 for (itr=temp; *itr!='\0'; itr++) { 239 while (fields[i].args[a]) {
148 *itr = apr_tolower(*itr); 240 printf("%s,", fields[i].args[a]);
241 a++;
242 }
243 }
244 printf(")");
149 } 245 }
150 return temp; 246 printf("\n");
247 }
248
249 printf("DryRun: %d\n", cfg->dryrun);
250 printf("Summary: %d\n", cfg->summary);
151} 251}
152 252
153#define config_get_option(name) apr_hash_get(g_config_opts, name, APR_HASH_KEY_STRING) 253#define config_get_option(name) apr_hash_get(g_config_opts, name, APR_HASH_KEY_STRING)
154 254
155void config_add_option(apr_pool_t *p, const char *const name, 255static void config_add_option(apr_pool_t *p, const char *const name,
156 const char *const help, config_func_t func, void *data) 256 const char *const help, config_func_t func, void *data)
157{ 257{
158 config_opt_t *opt; 258 config_opt_t *opt;
@@ -164,22 +264,24 @@ void config_add_option(apr_pool_t *p, const char *const name,
164 opt->help = help; 264 opt->help = help;
165 opt->func = func; 265 opt->func = func;
166 opt->data = data; 266 opt->data = data;
167 apr_hash_set(g_config_opts, lowerstr(p,name), APR_HASH_KEY_STRING, opt); 267 apr_hash_set(g_config_opts, lowerstr(p, name), APR_HASH_KEY_STRING, opt);
168} 268}
169 269
170void config_init(apr_pool_t *p) 270void config_init(apr_pool_t *p)
171{ 271{
172 config_add_option(p, "ErrorLog", "File to log errors", 272 config_add_option(p, "ErrorLog", "File to log errors", config_set_string,
173 config_set_string, (void *)APR_OFFSETOF(config_t, errorlog)); 273 (void *)APR_OFFSETOF(config_t, errorlog));
174 config_add_option(p, "LogLevel", "Set Log Level (error, warn, debug, quiet)", 274 config_add_option(p, "LogLevel",
175 config_set_loglevel, NULL); 275 "Set Log Level (error, warn, debug, quiet)", config_set_loglevel,
276 NULL);
176 277
177 config_add_option(p, "InputDirectory", "Directory to scan for log files", 278 config_add_option(p, "InputDirectory", "Directory to scan for log files",
178 config_set_string, (void *)APR_OFFSETOF(config_t, input_dir)); 279 config_set_string, (void *)APR_OFFSETOF(config_t, input_dir));
179 config_add_option(p, "InputFile", "Parse only this file", 280 config_add_option(p, "InputFile", "Parse only this file",
180 config_set_inputfile, NULL); 281 config_set_inputfile, NULL);
181 282
182 config_add_option(p, "DBConnect", "DB Connection information type://user:pass@hostname/database", 283 config_add_option(p, "DBConnect",
284 "DB Connection information type://user:pass@hostname/database",
183 config_set_dbconnect, NULL); 285 config_set_dbconnect, NULL);
184 config_add_option(p, "DBParam", "DB Connection Parameter", 286 config_add_option(p, "DBParam", "DB Connection Parameter",
185 config_set_dbparam, NULL); 287 config_set_dbparam, NULL);
@@ -187,14 +289,28 @@ void config_init(apr_pool_t *p)
187 config_set_string, (void *)APR_OFFSETOF(config_t, table)); 289 config_set_string, (void *)APR_OFFSETOF(config_t, table));
188 config_add_option(p, "UseTransactions", "Enable Transactions?", 290 config_add_option(p, "UseTransactions", "Enable Transactions?",
189 config_set_flag, (void *)APR_OFFSETOF(config_t, transactions)); 291 config_set_flag, (void *)APR_OFFSETOF(config_t, transactions));
190 config_add_option(p, "MachineID", "Machine ID to set", 292 config_add_option(p, "MachineID", "Machine ID to set", config_set_string,
191 config_set_string, (void *)APR_OFFSETOF(config_t, machineid)); 293 (void *)APR_OFFSETOF(config_t, machineid));
192 294
193 config_add_option(p, "LogFormatConfig", "Define input log formats", 295 config_add_option(p, "LogFormatConfig", "Define input log formats",
194 config_set_logformat, NULL); 296 config_set_logformat, NULL);
195 config_add_option(p, "LogFormat", "Use this logformat when parsing files", 297 config_add_option(p, "LogFormat", "Use this logformat when parsing files",
196 config_set_string, (void *)APR_OFFSETOF(config_t, logformat)); 298 config_set_string, (void *)APR_OFFSETOF(config_t, logformat));
197 299
300 config_add_option(p, "LineFilter",
301 "A regular expression to apply to the input line",
302 config_set_filter, (void *)APR_OFFSETOF(config_t, linefilters));
303 config_add_option(p, "PreFilter",
304 "A regular expression to apply to a specific input field",
305 config_set_filter, (void *)APR_OFFSETOF(config_t, prefilters));
306 config_add_option(p, "PostFilter",
307 "A regular expression to apply to a specific SQL output field",
308 config_set_filter, (void *)APR_OFFSETOF(config_t, postfilters));
309
310 config_add_option(p, "OutputField",
311 "Define output fields: field datatype source optfunc optarg...",
312 config_set_output_field, NULL);
313
198 config_add_option(p, "DryRun", "Don't perform any actual database changes", 314 config_add_option(p, "DryRun", "Don't perform any actual database changes",
199 config_set_flag, (void *)APR_OFFSETOF(config_t, dryrun)); 315 config_set_flag, (void *)APR_OFFSETOF(config_t, dryrun));
200 config_add_option(p, "Config", "Dummy to handle config directive", 316 config_add_option(p, "Config", "Dummy to handle config directive",
@@ -216,16 +332,20 @@ config_t *config_create(apr_pool_t *p)
216 cfg->input_files = apr_array_make(cfg->pool, 10, sizeof(char *)); 332 cfg->input_files = apr_array_make(cfg->pool, 10, sizeof(char *));
217 cfg->dbconfig = apr_table_make(cfg->pool, 5); 333 cfg->dbconfig = apr_table_make(cfg->pool, 5);
218 cfg->log_formats = apr_hash_make(cfg->pool); 334 cfg->log_formats = apr_hash_make(cfg->pool);
219 335 cfg->output_fields = apr_array_make(cfg->pool, 10,
336 sizeof(config_output_field_t));
220 return cfg; 337 return cfg;
221} 338}
222 339
223int config_merge(void *rec, const char *key, const char *value) { 340static int config_merge(void *rec, const char *key, const char *value)
341{
224 config_t *cfg = (config_t *)rec; 342 config_t *cfg = (config_t *)rec;
225 343
226 config_opt_t *opt = config_get_option(key); 344 config_opt_t *opt= config_get_option(key);
227 if (opt) { 345 if (opt) {
228 const char *args[] = {key, value}; 346 const char *args[] = {
347 key,
348 value };
229 opt->func(cfg, opt, 2, args); 349 opt->func(cfg, opt, 2, args);
230 } else { 350 } else {
231 printf("Unhandled: %s\n", key); 351 printf("Unhandled: %s\n", key);
@@ -238,11 +358,11 @@ apr_status_t config_read(config_t *cfg, const char *filename,
238{ 358{
239 apr_finfo_t finfo; 359 apr_finfo_t finfo;
240 apr_file_t *file; 360 apr_file_t *file;
241 apr_status_t rv, ret = APR_SUCCESS; 361 apr_status_t rv, ret= APR_SUCCESS;
242 apr_pool_t *tp, *targp; 362 apr_pool_t *tp, *targp;
243 config_opt_t *opt; 363 config_opt_t *opt;
244 char buff[1024]; 364 char buff[1024];
245 char *ptr, *ptr2; 365 char *ptr;
246 char **targv; 366 char **targv;
247 int targc; 367 int targc;
248 int line; 368 int line;
@@ -254,7 +374,7 @@ apr_status_t config_read(config_t *cfg, const char *filename,
254 return APR_ENOENT; 374 return APR_ENOENT;
255 } 375 }
256 rv = apr_file_open(&file, filename, APR_FOPEN_READ | APR_BUFFERED, 376 rv = apr_file_open(&file, filename, APR_FOPEN_READ | APR_BUFFERED,
257 APR_OS_DEFAULT, tp); 377 APR_OS_DEFAULT, tp);
258 if (rv != APR_SUCCESS) 378 if (rv != APR_SUCCESS)
259 return rv; 379 return rv;
260 380
@@ -267,10 +387,7 @@ apr_status_t config_read(config_t *cfg, const char *filename,
267 // skip leading white space 387 // skip leading white space
268 for (ptr = buff; *ptr == ' ' || *ptr == '\t'; ptr++) 388 for (ptr = buff; *ptr == ' ' || *ptr == '\t'; ptr++)
269 ; 389 ;
270 // chomp off newline 390 line_chomp(ptr);
271 for (ptr2 = ptr + strlen(ptr); *ptr2 != '\r' && *ptr2 != '\n'; ptr2--)
272 ;
273 *ptr2 = '\0';
274 391
275 // skip comments 392 // skip comments
276 if (*ptr == '#') 393 if (*ptr == '#')
@@ -278,9 +395,10 @@ apr_status_t config_read(config_t *cfg, const char *filename,
278 if (*ptr == '\0') 395 if (*ptr == '\0')
279 continue; 396 continue;
280 apr_pool_clear(targp); 397 apr_pool_clear(targp);
281 apr_tokenize_to_argv(buff, &targv, targp); 398 apr_tokenize_to_argv(ptr, &targv, targp);
282 targc = 0; 399 targc = 0;
283 while (targv[targc]) targc++; 400 while (targv[targc])
401 targc++;
284 opt = config_get_option(lowerstr(targp,targv[0])); 402 opt = config_get_option(lowerstr(targp,targv[0]));
285 if (opt) { 403 if (opt) {
286 rv = opt->func(cfg, opt, targc, (const char **)targv); 404 rv = opt->func(cfg, opt, targc, (const char **)targv);
@@ -296,10 +414,9 @@ apr_status_t config_read(config_t *cfg, const char *filename,
296 } while (rv == APR_SUCCESS); 414 } while (rv == APR_SUCCESS);
297 415
298 // Apply merges 416 // Apply merges
299 apr_table_do(config_merge,(void *)cfg,merge,NULL); 417 apr_table_do(config_merge, (void *)cfg, merge, NULL);
300 418
301 apr_file_close(file); 419 apr_file_close(file);
302 apr_pool_destroy(tp); 420 apr_pool_destroy(tp);
303 return ret; 421 return ret;
304} 422}
305