|
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 |
}
|