Blame src/lognormalizer.c

Packit 1422b7
/**
Packit 1422b7
 * @file normalizer.c
Packit 1422b7
 * @brief A small tool to normalize data.
Packit 1422b7
 *
Packit 1422b7
 * This is the most basic example demonstrating how to use liblognorm.
Packit 1422b7
 * It loads log samples from the files specified on the command line,
Packit 1422b7
 * reads to-be-normalized data from stdin and writes the normalized
Packit 1422b7
 * form to stdout. Besides being an example, it also carries out useful
Packit 1422b7
 * processing.
Packit 1422b7
 *
Packit 1422b7
 * @author Rainer Gerhards <rgerhards@adiscon.com>
Packit 1422b7
 *
Packit 1422b7
 *//*
Packit 1422b7
 * liblognorm - a fast samples-based log normalization library
Packit 1422b7
 * Copyright 2010-2016 by Rainer Gerhards and Adiscon GmbH.
Packit 1422b7
 *
Packit 1422b7
 * This file is part of liblognorm.
Packit 1422b7
 *
Packit 1422b7
 * This library is free software; you can redistribute it and/or
Packit 1422b7
 * modify it under the terms of the GNU Lesser General Public
Packit 1422b7
 * License as published by the Free Software Foundation; either
Packit 1422b7
 * version 2.1 of the License, or (at your option) any later version.
Packit 1422b7
 *
Packit 1422b7
 * This library is distributed in the hope that it will be useful,
Packit 1422b7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1422b7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 1422b7
 * Lesser General Public License for more details.
Packit 1422b7
 *
Packit 1422b7
 * You should have received a copy of the GNU Lesser General Public
Packit 1422b7
 * License along with this library; if not, write to the Free Software
Packit 1422b7
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 1422b7
 *
Packit 1422b7
 * A copy of the LGPL v2.1 can be found in the file "COPYING" in this distribution.
Packit 1422b7
 */
Packit 1422b7
#include "config.h"
Packit 1422b7
#include <stdio.h>
Packit 1422b7
#include <string.h>
Packit 1422b7
#include <getopt.h>
Packit 1422b7
#include <libestr.h>
Packit 1422b7
Packit 1422b7
#include "liblognorm.h"
Packit 1422b7
#include "lognorm.h"
Packit 1422b7
#include "enc.h"
Packit 1422b7
Packit 1422b7
/* we need to turn off this warning, as it also comes up in C99 mode, which
Packit 1422b7
 * we use.
Packit 1422b7
 */
Packit 1422b7
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
Packit 1422b7
Packit 1422b7
static ln_ctx ctx;
Packit 1422b7
Packit 1422b7
static int verbose = 0;
Packit 1422b7
#define OUTPUT_PARSED_RECS 0x01
Packit 1422b7
#define OUTPUT_UNPARSED_RECS 0x02
Packit 1422b7
static int recOutput = OUTPUT_PARSED_RECS | OUTPUT_UNPARSED_RECS;
Packit 1422b7
				/**< controls which records to output */
Packit 1422b7
static int outputSummaryLine = 0;
Packit 1422b7
static int outputNbrUnparsed = 0;
Packit 1422b7
static int addErrLineNbr = 0;	/**< add line number info to unparsed events */
Packit 1422b7
static int flatTags = 0;	/**< print event.tags in JSON? */
Packit 1422b7
static FILE *fpDOT;
Packit 1422b7
static es_str_t *encFmt = NULL; /**< a format string for encoder use */
Packit 1422b7
static es_str_t *mandatoryTag = NULL; /**< tag which must be given so that mesg will
Packit 1422b7
					   be output. NULL=all */
Packit 1422b7
static enum { f_syslog, f_json, f_xml, f_csv, f_raw } outfmt = f_json;
Packit 1422b7
Packit 1422b7
static void
Packit 1422b7
errCallBack(void __attribute__((unused)) *cookie, const char *msg,
Packit 1422b7
	    size_t __attribute__((unused)) lenMsg)
Packit 1422b7
{
Packit 1422b7
	fprintf(stderr, "liblognorm error: %s\n", msg);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
static void
Packit 1422b7
dbgCallBack(void __attribute__((unused)) *cookie, const char *msg,
Packit 1422b7
	    size_t __attribute__((unused)) lenMsg)
Packit 1422b7
{
Packit 1422b7
	fprintf(stderr, "liblognorm: %s\n", msg);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
static void
Packit 1422b7
complain(const char *errmsg)
Packit 1422b7
{
Packit 1422b7
	fprintf(stderr, "%s\n", errmsg);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
Packit 1422b7
/* rawmsg is, as the name says, the raw message, in case we have
Packit 1422b7
 * "raw" formatter requested.
Packit 1422b7
 */
Packit 1422b7
static void
Packit 1422b7
outputEvent(struct json_object *json, const char *const rawmsg)
Packit 1422b7
{
Packit 1422b7
	char *cstr = NULL;
Packit 1422b7
	es_str_t *str = NULL;
Packit 1422b7
Packit 1422b7
	if(outfmt == f_raw) {
Packit 1422b7
		printf("%s\n", rawmsg);
Packit 1422b7
		return;
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	switch(outfmt) {
Packit 1422b7
	case f_json:
Packit 1422b7
		if(!flatTags) {
Packit 1422b7
			json_object_object_del(json, "event.tags");
Packit 1422b7
		}
Packit 1422b7
		cstr = (char*)json_object_to_json_string(json);
Packit 1422b7
		break;
Packit 1422b7
	case f_syslog:
Packit 1422b7
		ln_fmtEventToRFC5424(json, &str);
Packit 1422b7
		break;
Packit 1422b7
	case f_xml:
Packit 1422b7
		ln_fmtEventToXML(json, &str);
Packit 1422b7
		break;
Packit 1422b7
	case f_csv:
Packit 1422b7
		ln_fmtEventToCSV(json, &str, encFmt);
Packit 1422b7
		break;
Packit 1422b7
	case f_raw:
Packit 1422b7
		fprintf(stderr, "program error: f_raw should not occur "
Packit 1422b7
			"here (file %s, line %d)\n", __FILE__, __LINE__);
Packit 1422b7
		abort();
Packit 1422b7
		break;
Packit 1422b7
	default:
Packit 1422b7
		fprintf(stderr, "program error: default case should not occur "
Packit 1422b7
			"here (file %s, line %d)\n", __FILE__, __LINE__);
Packit 1422b7
		abort();
Packit 1422b7
		break;
Packit 1422b7
	}
Packit 1422b7
	if (str != NULL)
Packit 1422b7
		cstr = es_str2cstr(str, NULL);
Packit 1422b7
	if(verbose > 0) fprintf(stderr, "normalized: '%s'\n", cstr);
Packit 1422b7
	printf("%s\n", cstr);
Packit 1422b7
	if (str != NULL)
Packit 1422b7
		free(cstr);
Packit 1422b7
	es_deleteStr(str);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
/* test if the tag exists */
Packit 1422b7
static int
Packit 1422b7
eventHasTag(struct json_object *json, const char *tag)
Packit 1422b7
{
Packit 1422b7
	struct json_object *tagbucket, *tagObj;
Packit 1422b7
	int i;
Packit 1422b7
	const char *tagCstr;
Packit 1422b7
	
Packit 1422b7
	if (tag == NULL)
Packit 1422b7
		return 1;
Packit 1422b7
	if (json_object_object_get_ex(json, "event.tags", &tagbucket)) {
Packit 1422b7
		if (json_object_get_type(tagbucket) == json_type_array) {
Packit 1422b7
			for (i = json_object_array_length(tagbucket) - 1; i >= 0; i--) {
Packit 1422b7
				tagObj = json_object_array_get_idx(tagbucket, i);
Packit 1422b7
				tagCstr = json_object_get_string(tagObj);
Packit 1422b7
				if (!strcmp(tag, tagCstr))
Packit 1422b7
					return 1;
Packit 1422b7
			}
Packit 1422b7
		}
Packit 1422b7
	}
Packit 1422b7
	if (verbose > 1)
Packit 1422b7
		printf("Mandatory tag '%s' has not been found\n", tag);
Packit 1422b7
	return 0;
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
static void
Packit 1422b7
amendLineNbr(json_object *const json, const int line_nbr)
Packit 1422b7
{
Packit 1422b7
	
Packit 1422b7
	if(addErrLineNbr) {
Packit 1422b7
		struct json_object *jval;
Packit 1422b7
		jval = json_object_new_int(line_nbr);
Packit 1422b7
		json_object_object_add(json, "lognormalizer.line_nbr", jval);
Packit 1422b7
	}
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
#define DEFAULT_LINE_SIZE (10 * 1024)
Packit 1422b7
Packit 1422b7
static char *
Packit 1422b7
read_line(FILE *fp)
Packit 1422b7
{
Packit 1422b7
	size_t line_capacity = DEFAULT_LINE_SIZE;
Packit 1422b7
	char *line = NULL;
Packit 1422b7
	size_t line_len = 0;
Packit 1422b7
	int ch = 0;
Packit 1422b7
	do {
Packit 1422b7
		ch = fgetc(fp);
Packit 1422b7
		if (ch == EOF) break;
Packit 1422b7
		if (line == NULL) {
Packit 1422b7
			line = malloc(line_capacity);
Packit 1422b7
		} else if (line_len == line_capacity) {
Packit 1422b7
			line_capacity *= 2;
Packit 1422b7
			line = realloc(line, line_capacity);
Packit 1422b7
		}
Packit 1422b7
		if (line == NULL) {
Packit 1422b7
			fprintf(stderr, "Couldn't allocate working-buffer for log-line\n");
Packit 1422b7
			return NULL;
Packit 1422b7
		}
Packit 1422b7
		line[line_len++] = ch;
Packit 1422b7
	} while(ch != '\n');
Packit 1422b7
Packit 1422b7
	if (line != NULL) {
Packit 1422b7
		line[--line_len] = '\0';
Packit 1422b7
		if(line_len > 0 && line[line_len - 1] == '\r')
Packit 1422b7
			line[--line_len] = '\0';
Packit 1422b7
	}
Packit 1422b7
	return line;
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
/* normalize input data
Packit 1422b7
 */
Packit 1422b7
static void
Packit 1422b7
normalize(void)
Packit 1422b7
{
Packit 1422b7
	FILE *fp = stdin;
Packit 1422b7
	char *line = NULL;
Packit 1422b7
	struct json_object *json = NULL;
Packit 1422b7
	long long unsigned numParsed = 0;
Packit 1422b7
	long long unsigned numUnparsed = 0;
Packit 1422b7
	long long unsigned numWrongTag = 0;
Packit 1422b7
	char *mandatoryTagCstr = NULL;
Packit 1422b7
	int line_nbr = 0;	/* must be int to keep compatible with older json-c */
Packit 1422b7
Packit 1422b7
	if (mandatoryTag != NULL) {
Packit 1422b7
		mandatoryTagCstr = es_str2cstr(mandatoryTag, NULL);
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	while((line = read_line(fp)) != NULL) {
Packit 1422b7
		++line_nbr;
Packit 1422b7
		if(verbose > 0) fprintf(stderr, "To normalize: '%s'\n", line);
Packit 1422b7
		ln_normalize(ctx, line, strlen(line), &json);
Packit 1422b7
		if(json != NULL) {
Packit 1422b7
			if(eventHasTag(json, mandatoryTagCstr)) {
Packit 1422b7
				struct json_object *dummy;
Packit 1422b7
				const int parsed = !json_object_object_get_ex(json,
Packit 1422b7
					"unparsed-data", &dummy);
Packit 1422b7
				if(parsed) {
Packit 1422b7
					numParsed++;
Packit 1422b7
					if(recOutput & OUTPUT_PARSED_RECS) {
Packit 1422b7
						outputEvent(json, line);
Packit 1422b7
					}
Packit 1422b7
				} else {
Packit 1422b7
					numUnparsed++;
Packit 1422b7
					amendLineNbr(json, line_nbr);
Packit 1422b7
					if(recOutput & OUTPUT_UNPARSED_RECS) {
Packit 1422b7
						outputEvent(json, line);
Packit 1422b7
					}
Packit 1422b7
				}
Packit 1422b7
			} else {
Packit 1422b7
				numWrongTag++;
Packit 1422b7
			}
Packit 1422b7
			json_object_put(json);
Packit 1422b7
			json = NULL;
Packit 1422b7
		}
Packit 1422b7
	free(line);
Packit 1422b7
	}
Packit 1422b7
	if(outputNbrUnparsed && numUnparsed > 0)
Packit 1422b7
		fprintf(stderr, "%llu unparsable entries\n", numUnparsed);
Packit 1422b7
	if(numWrongTag > 0)
Packit 1422b7
		fprintf(stderr, "%llu entries with wrong tag dropped\n", numWrongTag);
Packit 1422b7
	if(outputSummaryLine) {
Packit 1422b7
		fprintf(stderr, "%llu records processed, %llu parsed, %llu unparsed\n",
Packit 1422b7
			numParsed+numUnparsed, numParsed, numUnparsed);
Packit 1422b7
	}
Packit 1422b7
	free(mandatoryTagCstr);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
Packit 1422b7
/**
Packit 1422b7
 * Generate a command file for the GNU DOT tools.
Packit 1422b7
 */
Packit 1422b7
static void
Packit 1422b7
genDOT(void)
Packit 1422b7
{
Packit 1422b7
	es_str_t *str;
Packit 1422b7
Packit 1422b7
	str = es_newStr(1024);
Packit 1422b7
	ln_genDotPDAGGraph(ctx->pdag, &str);
Packit 1422b7
	fwrite(es_getBufAddr(str), 1, es_strlen(str), fpDOT);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
static
Packit 1422b7
void printVersion(void)
Packit 1422b7
{
Packit 1422b7
	fprintf(stderr, "lognormalizer version: " VERSION "\n");
Packit 1422b7
	fprintf(stderr, "liblognorm version: %s\n", ln_version());
Packit 1422b7
	fprintf(stderr, "\tadvanced stats: %s\n",
Packit 1422b7
		ln_hasAdvancedStats() ? "available" : "not available");
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
static void
Packit 1422b7
handle_generic_option(const char* opt) {
Packit 1422b7
	if (strcmp("allowRegex", opt) == 0) {
Packit 1422b7
		ln_setCtxOpts(ctx, LN_CTXOPT_ALLOW_REGEX);
Packit 1422b7
	} else if (strcmp("addExecPath", opt) == 0) {
Packit 1422b7
		ln_setCtxOpts(ctx, LN_CTXOPT_ADD_EXEC_PATH);
Packit 1422b7
	} else if (strcmp("addOriginalMsg", opt) == 0) {
Packit 1422b7
		ln_setCtxOpts(ctx, LN_CTXOPT_ADD_ORIGINALMSG);
Packit 1422b7
	} else if (strcmp("addRule", opt) == 0) {
Packit 1422b7
		ln_setCtxOpts(ctx, LN_CTXOPT_ADD_RULE);
Packit 1422b7
	} else if (strcmp("addRuleLocation", opt) == 0) {
Packit 1422b7
		ln_setCtxOpts(ctx, LN_CTXOPT_ADD_RULE_LOCATION);
Packit 1422b7
	} else {
Packit 1422b7
		fprintf(stderr, "invalid -o option '%s'\n", opt);
Packit 1422b7
		exit(1);
Packit 1422b7
	}
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
static void usage(void)
Packit 1422b7
{
Packit 1422b7
fprintf(stderr,
Packit 1422b7
	"Options:\n"
Packit 1422b7
	"    -r<rulebase> Rulebase to use. This is required option\n"
Packit 1422b7
	"    -H           print summary line (nbr of msgs Handled)\n"
Packit 1422b7
	"    -U           print number of unparsed messages (only if non-zero)\n"
Packit 1422b7
	"    -e<json|xml|csv|cee-syslog|raw>\n"
Packit 1422b7
	"                 Change output format. By default, json is used\n"
Packit 1422b7
	"                 Raw is exactly like the input. It is useful in combination\n"
Packit 1422b7
	"                 with -p/-P options to extract known good/bad messages\n"
Packit 1422b7
	"    -E<format>   Encoder-specific format (used for CSV, read docs)\n"
Packit 1422b7
	"    -T           Include 'event.tags' in JSON format\n"
Packit 1422b7
	"    -oallowRegex Allow regexp matching (read docs about performance penalty)\n"
Packit 1422b7
	"    -oaddRule    Add a mockup of the matching rule.\n"
Packit 1422b7
	"    -oaddRuleLocation Add location of matching rule to metadata\n"
Packit 1422b7
	"    -oaddExecPath Add exec_path attribute to output\n"
Packit 1422b7
	"    -oaddOriginalMsg Always add original message to output, not just in error case\n"
Packit 1422b7
	"    -p           Print back only if the message has been parsed succesfully\n"
Packit 1422b7
	"    -P           Print back only if the message has NOT been parsed succesfully\n"
Packit 1422b7
	"    -L           Add source file line number information to unparsed line output\n"
Packit 1422b7
	"    -t<tag>      Print back only messages matching the tag\n"
Packit 1422b7
	"    -v           Print debug. When used 3 times, prints parse DAG\n"
Packit 1422b7
	"    -V           Print version information\n"
Packit 1422b7
	"    -d           Print DOT file to stdout and exit\n"
Packit 1422b7
	"    -d<filename> Save DOT file to the filename\n"
Packit 1422b7
	"    -s<filename> Print parse dag statistics and exit\n"
Packit 1422b7
	"    -S<filename> Print extended parse dag statistics and exit (includes -s)\n"
Packit 1422b7
	"    -x<filename> Print statistics as dot file (called only)\n"
Packit 1422b7
	"\n"
Packit 1422b7
	);
Packit 1422b7
}
Packit 1422b7
Packit 1422b7
int main(int argc, char *argv[])
Packit 1422b7
{
Packit 1422b7
	int opt;
Packit 1422b7
	char *repository = NULL;
Packit 1422b7
	int usedRB = 0; /* 0=no rule; 1=rule from rulebase; 2=rule from string */
Packit 1422b7
	int ret = 0;
Packit 1422b7
	FILE *fpStats = NULL;
Packit 1422b7
	FILE *fpStatsDOT = NULL;
Packit 1422b7
	int extendedStats = 0;
Packit 1422b7
Packit 1422b7
	if((ctx = ln_initCtx()) == NULL) {
Packit 1422b7
		complain("Could not initialize liblognorm context");
Packit 1422b7
		ret = 1;
Packit 1422b7
		goto exit;
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	while((opt = getopt(argc, argv, "d:s:S:e:r:R:E:vVpPt:To:hHULx:")) != -1) {
Packit 1422b7
		switch (opt) {
Packit 1422b7
		case 'V':
Packit 1422b7
			printVersion();
Packit 1422b7
			exit(1);
Packit 1422b7
			break;
Packit 1422b7
		case 'd': /* generate DOT file */
Packit 1422b7
			if(!strcmp(optarg, "")) {
Packit 1422b7
				fpDOT = stdout;
Packit 1422b7
			} else {
Packit 1422b7
				if((fpDOT = fopen(optarg, "w")) == NULL) {
Packit 1422b7
					perror(optarg);
Packit 1422b7
					complain("Cannot open DOT file");
Packit 1422b7
					ret = 1;
Packit 1422b7
					goto exit;
Packit 1422b7
				}
Packit 1422b7
			}
Packit 1422b7
			break;
Packit 1422b7
		case 'x': /* generate statistics DOT file */
Packit 1422b7
			if(!strcmp(optarg, "")) {
Packit 1422b7
				fpStatsDOT = stdout;
Packit 1422b7
			} else {
Packit 1422b7
				if((fpStatsDOT = fopen(optarg, "w")) == NULL) {
Packit 1422b7
					perror(optarg);
Packit 1422b7
					complain("Cannot open statistics DOT file");
Packit 1422b7
					ret = 1;
Packit 1422b7
					goto exit;
Packit 1422b7
				}
Packit 1422b7
			}
Packit 1422b7
			break;
Packit 1422b7
		case 'S': /* generate pdag statistic file */
Packit 1422b7
			extendedStats = 1;
Packit 1422b7
			/* INTENTIONALLY NO BREAK! - KEEP order! */
Packit 1422b7
			/*FALLTHROUGH*/
Packit 1422b7
		case 's': /* generate pdag statistic file */
Packit 1422b7
			if(!strcmp(optarg, "-")) {
Packit 1422b7
				fpStats = stdout;
Packit 1422b7
			} else {
Packit 1422b7
				if((fpStats = fopen(optarg, "w")) == NULL) {
Packit 1422b7
					perror(optarg);
Packit 1422b7
					complain("Cannot open parser statistics file");
Packit 1422b7
					ret = 1;
Packit 1422b7
					goto exit;
Packit 1422b7
				}
Packit 1422b7
			}
Packit 1422b7
			break;
Packit 1422b7
		case 'v':
Packit 1422b7
			verbose++;
Packit 1422b7
			break;
Packit 1422b7
		case 'E': /* encoder-specific format string (will be validated by encoder) */
Packit 1422b7
			encFmt = es_newStrFromCStr(optarg, strlen(optarg));
Packit 1422b7
			break;
Packit 1422b7
		case 'p':
Packit 1422b7
			recOutput = OUTPUT_PARSED_RECS;
Packit 1422b7
			break;
Packit 1422b7
		case 'P':
Packit 1422b7
			recOutput = OUTPUT_UNPARSED_RECS;
Packit 1422b7
			break;
Packit 1422b7
		case 'H':
Packit 1422b7
			outputSummaryLine = 1;
Packit 1422b7
			break;
Packit 1422b7
		case 'U':
Packit 1422b7
			outputNbrUnparsed = 1;
Packit 1422b7
			break;
Packit 1422b7
		case 'L':
Packit 1422b7
			addErrLineNbr = 1;
Packit 1422b7
			break;
Packit 1422b7
		case 'T':
Packit 1422b7
			flatTags = 1;
Packit 1422b7
			break;
Packit 1422b7
		case 'e': /* encoder to use */
Packit 1422b7
			if(!strcmp(optarg, "json")) {
Packit 1422b7
				outfmt = f_json;
Packit 1422b7
			} else if(!strcmp(optarg, "xml")) {
Packit 1422b7
				outfmt = f_xml;
Packit 1422b7
			} else if(!strcmp(optarg, "cee-syslog")) {
Packit 1422b7
				outfmt = f_syslog;
Packit 1422b7
			} else if(!strcmp(optarg, "csv")) {
Packit 1422b7
				outfmt = f_csv;
Packit 1422b7
			} else if(!strcmp(optarg, "raw")) {
Packit 1422b7
				outfmt = f_raw;
Packit 1422b7
			}
Packit 1422b7
			break;
Packit 1422b7
		case 'r': /* rule base to use */
Packit 1422b7
			if(usedRB != 2) {
Packit 1422b7
				repository = optarg;
Packit 1422b7
				usedRB = 1;
Packit 1422b7
			} else {
Packit 1422b7
				usedRB = -1;
Packit 1422b7
			}
Packit 1422b7
			break;
Packit 1422b7
		case 'R':
Packit 1422b7
			if(usedRB != 1) {
Packit 1422b7
				repository = optarg;
Packit 1422b7
				usedRB = 2;
Packit 1422b7
			} else {
Packit 1422b7
				usedRB = -1;
Packit 1422b7
			}
Packit 1422b7
			break;
Packit 1422b7
		case 't': /* if given, only messages tagged with the argument
Packit 1422b7
			     are output */
Packit 1422b7
			mandatoryTag = es_newStrFromCStr(optarg, strlen(optarg));
Packit 1422b7
			break;
Packit 1422b7
		case 'o':
Packit 1422b7
			handle_generic_option(optarg);
Packit 1422b7
			break;
Packit 1422b7
		case 'h':
Packit 1422b7
		default:
Packit 1422b7
			usage();
Packit 1422b7
			ret = 1;
Packit 1422b7
			goto exit;
Packit 1422b7
			break;
Packit 1422b7
		}
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	if(repository == NULL) {
Packit 1422b7
		complain("Samples repository or String must be given (-r or -R)");
Packit 1422b7
		ret = 1;
Packit 1422b7
		goto exit;
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	if(usedRB == -1) {
Packit 1422b7
		complain("Only use one rulebase (-r or -R)");
Packit 1422b7
		ret = 1;
Packit 1422b7
		goto exit;
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	ln_setErrMsgCB(ctx, errCallBack, NULL);
Packit 1422b7
	if(verbose) {
Packit 1422b7
		ln_setDebugCB(ctx, dbgCallBack, NULL);
Packit 1422b7
		ln_enableDebug(ctx, 1);
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	if(usedRB == 1) {
Packit 1422b7
		if(ln_loadSamples(ctx, repository)) {
Packit 1422b7
			fprintf(stderr, "fatal error: cannot load rulebase\n");
Packit 1422b7
			exit(1);
Packit 1422b7
		}
Packit 1422b7
	} else if(usedRB == 2) {
Packit 1422b7
		if(ln_loadSamplesFromString(ctx, repository)) {
Packit 1422b7
			fprintf(stderr, "fatal error: cannot load rule from String\n");
Packit 1422b7
			exit(1);
Packit 1422b7
		}
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	if(verbose > 0)
Packit 1422b7
		fprintf(stderr, "number of tree nodes: %d\n", ctx->nNodes);
Packit 1422b7
Packit 1422b7
	if(fpDOT != NULL) {
Packit 1422b7
		genDOT();
Packit 1422b7
		ret=1;
Packit 1422b7
		goto exit;
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	if(verbose > 2) ln_displayPDAG(ctx);
Packit 1422b7
Packit 1422b7
	normalize();
Packit 1422b7
Packit 1422b7
	if(fpStats != NULL) {
Packit 1422b7
		ln_fullPdagStats(ctx, fpStats, extendedStats);
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
	if(fpStatsDOT != NULL) {
Packit 1422b7
		ln_fullPDagStatsDOT(ctx, fpStatsDOT);
Packit 1422b7
	}
Packit 1422b7
Packit 1422b7
exit:
Packit 1422b7
	if (ctx) ln_exitCtx(ctx);
Packit 1422b7
	if (encFmt != NULL)
Packit 1422b7
		free(encFmt);
Packit 1422b7
	return ret;
Packit 1422b7
}