/*
* Copyright (c) 2001, 2002, 2003, 2004, 2005 Netli, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ncnf-validator.c,v 1.1 2005/05/26 12:08:19 vlm Exp $
*/
#include "headers.h"
#include "ncnf.h"
#include "ncnf_app.h"
#undef SUPPORT_NCQL
#ifdef HAVE_LIBSTRFUNC
#define SUPPORT_NCQL
#endif /* HAVE_LIBSTRFUNC */
#ifdef SUPPORT_NCQL
/*
* NCQL is only supported when libstrfunc was around when building NCNF.
*/
#include "ncnf_ql.h"
#endif /* SUPPORT_NCQL */
void usage(const char *);
int
main(int ac, char **av) {
ncnf_obj *root = NULL;
ncnf_obj *start_obj;
char *start_path = NULL;/* -S controls that */
int validate = 1; /* -V disables that */
int verbose = 0; /* -v enables that */
int indent = 4; /* -i controls that */
char *output_file = 0; /* -o controls that */
int profile_mode = 0; /* -p enables that */
int reload_times = 0; /* -r controls that */
int silent = 0; /* -s enables that */
char *flatten_type = 0; /* -t controls that */
ncnf_sf_svect *query_files = 0; /* -Q controls that */
int rld;
int ch;
while((ch = getopt(ac, av,
#ifdef SUPPORT_NCQL
"Q:"
#endif /* SUPPORT_NCQL */
"P:S:i:mo:pr:st:Vv")) != -1)
switch(ch) {
case 'Q':
if(!query_files) query_files = ncnf_sf_sinit();
ncnf_sf_sadd(query_files, optarg);
break;
case 'S':
case 'P':
if(start_path) {
fprintf(stderr, "-S used twice\n");
usage(av[0]);
}
start_path = optarg;
break;
case 'i':
indent = atoi(optarg);
if(indent > 8)
indent = 8;
else if(indent < 1)
indent = 1;
break;
case 'o':
if(output_file) {
fprintf(stderr, "-o used twice\n");
usage(av[0]);
}
output_file = optarg;
break;
case 'p':
profile_mode = 1;
break;
case 'r':
reload_times = atoi(optarg);
if(reload_times < 0)
reload_times = 0;
break;
case 's':
silent = 1;
break;
case 't':
flatten_type = optarg;
/* Fall through */
case 'V':
validate = 0;
break;
case 'v':
verbose = 1;
break;
default:
usage(av[0]);
}
ac -= optind;
av += optind;
if(silent && output_file) {
fprintf(stderr, "-s and -o cannot be used simultaneously\n");
usage(av[-optind]);
}
if(ac <= 0 || ac > (reload_times + 1)) {
if(ac > 0)
fprintf(stderr,
"ERROR: Number of -r reloads is insufficient "
"to cover the supplied files\n");
usage(av[-optind]);
}
for(rld = 0; rld <= reload_times; rld++) {
/* Read the ncnf file, optionally disabling validation */
ncnf_obj *new_root = ncnf_Read(av[rld % ac], NCNF_ST_FILENAME
| (validate ? 0 : (NCNF_FL_NODYN | NCNF_FL_NOEMB)));
if(new_root == NULL) {
perror("Failed to read configuration file");
return 1;
}
if(reload_times && root) {
int ret;
if(profile_mode)
printf("Merging the files\n");
ret = ncnf_diff(root, new_root);
assert(ret == 0);
if(profile_mode)
printf("Destroying processed new root\n");
ncnf_destroy(new_root);
} else {
root = new_root;
}
#ifdef SUPPORT_NCQL
/* -Q in operation */
if(query_files) {
int i;
ncnf_clear_query(root ? root : new_root);
for(i = 0; i < query_files->count; i++) {
char errbuf[256];
size_t errlen = sizeof(errbuf);
ncnf_query_t *nq;
ncnf_obj *ncql = ncnf_Read(
query_files->list[i],
NCNF_ST_FILENAME
/* Never use embedded validation */
| NCNF_FL_NOEMB
/* Relaxed namespace rules */
| NCNF_FL_RELNS);
if(!ncql) {
fprintf(stderr,
"-Q %s: Failed to read file: %s\n",
query_files->list[i],
strerror(errno));
return 1;
}
nq = ncnf_compile_query(ncql, errbuf, &errlen);
ncnf_destroy(ncql);
if(!nq) {
fprintf(stderr, "-Q %s: %s\n",
query_files->list[i],
errbuf);
return 1;
}
ncnf_exec_query(root ? root : new_root, nq, 0);
ncnf_delete_query(nq);
}
}
#endif /* SUPPORT_NCQL */
if(profile_mode) {
int sleep_time = 10;
if(rld < reload_times) {
printf("Wait %ds before %d reload%s\n",
sleep_time,
reload_times - rld,
(reload_times - rld == 1) ? "" : "s"
);
} else {
sleep_time = 10;
printf("Waiting a bit before exit...\n");
}
sleep(sleep_time);
printf("Waiting finished.\n");
if(rld == reload_times)
exit(2);
}
}
assert(root);
if(start_path) {
if(strchr(start_path, '@')) {
start_obj = NCNF_APP_resolve_sysid(root, start_path);
} else {
start_obj = NCNF_APP_resolve_path(root, start_path);
}
if(start_obj == NULL) {
fprintf(stderr, "Entity not found: %s: %s\n",
start_path, strerror(errno));
exit(EX_DATAERR);
}
} else {
start_obj = root;
}
/*
* Print config nicely.
*/
if(!silent) {
FILE *ofile = stdout;
if(output_file) {
ofile = fopen(output_file, "w");
if(!ofile) {
fprintf(stderr, "Cannot save %s: %s",
output_file, strerror(errno));
exit(EX_OSERR);
}
}
ncnf_dump(ofile, start_obj, flatten_type,
query_files ? 1 : 0, verbose, indent);
}
ncnf_destroy(root);
fprintf(stderr, "%s: %s\n", *av, validate ? "Validated" : "Parsed");
return 0;
}
void
usage(const char *av0) {
fprintf(stderr,
"Configuration file validator (c) 2002, 03, 04, 2005 Netli, Inc.\n"
"Usage: %s [-impQrsStvV] <ncnf_config_file> ...\n"
"Options:\n"
" -i <indent> Use indentation spaces\n"
" -o <ofile.ncnf> Specify output file instead of default stdout\n"
" -p Profile mode (sleep() & exit())\n"
#ifdef SUPPORT_NCQL
" -Q <file.ncql> Perform NCQL query using specified query file\n"
#endif /* SUPPORT_NCQL */
" -r <num> Reload <num> times\n"
" -s Suppress file contents print-out (cmp. -v)\n"
" -S <subtree> Specify @sysid or /path of the subtree to dump\n"
" -t <type> \"Flatten\" the type. Put \"-\" for all types\n"
" -v Turn on verbose contents print-out mode (cmp. -s)\n"
" -V Disable validation\n"
, av0);
exit(EX_USAGE);
}
syntax highlighted by Code2HTML, v. 0.9.1