/* ** Modular Logfile Analyzer ** Copyright 2000 Jan Kneschke ** ** Homepage: http://www.modlogan.org ** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version, and provided that the above copyright and permission notice is included with all distributed copies of this or derived software. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ** ** $Id: parse.c,v 1.9 2003/04/18 18:36:56 ostborn Exp $ */ #include #include #include #include #include #include #include "mlocale.h" #include "mplugins.h" #include "mrecord.h" #include "mdatatypes.h" #include "misc.h" #include "plugin_config.h" const char *short_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; int parse_timestamp(mconfig *ext_conf, const char *str, mlogrec *record) { #define N 20 + 1 int ovector[3 * N], n, i; char buf[10]; struct tm tm; config_input *conf = ext_conf->plugin_conf; if ((n = pcre_exec(conf->match_timestamp, conf->match_timestamp_extra, str, strlen(str), 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, str); } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); } return -1; } memset(&tm, 0, sizeof(struct tm)); /* everything has matched, take the different pieces and be happy :) */ pcre_copy_substring(str, ovector, n, 1, buf, sizeof(buf)); for (i = 0; short_month[i];i++) { if (!strcmp(buf, short_month[i])) { tm.tm_mon = i; } } pcre_copy_substring(str, ovector, n, 2, buf, sizeof(buf)); tm.tm_mday = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 3, buf, sizeof(buf)); tm.tm_hour = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 4, buf, sizeof(buf)); tm.tm_min = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 5, buf, sizeof(buf)); tm.tm_sec = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 6, buf, sizeof(buf)); tm.tm_year = strtol(buf, NULL, 10)-1900; record->timestamp = mktime (&tm); return 0; #undef N } int parse_duration(mconfig *ext_conf, const char *str, mlogrec_telecom *record) { #define N 20 + 1 int ovector[3 * N], n; char buf[10]; config_input *conf = ext_conf->plugin_conf; if ((n = pcre_exec(conf->match_duration, conf->match_duration_extra, str, strlen(str), 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, str); } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); } return -1; } pcre_copy_substring(str, ovector, n, 1, buf, sizeof(buf)); record->duration = strtol(buf, NULL, 10) * 60 * 60; pcre_copy_substring(str, ovector, n, 2, buf, sizeof(buf)); record->duration += strtol(buf, NULL, 10) * 60; pcre_copy_substring(str, ovector, n, 3, buf, sizeof(buf)); record->duration += strtol(buf, NULL, 10); return 0; #undef N } int parse_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b) { #define N 22 + 1 const char **list; int ovector[3 * N], n; config_input *conf = ext_conf->plugin_conf; mlogrec_telecom *rectel = NULL; mlogrec_telecom_internal *recint = NULL; record->ext_type = M_RECORD_TYPE_TELECOM; record->ext = mrecord_init_telecom(); rectel = record->ext; if (rectel == NULL) return -1; /* parse the record */ if ((n = pcre_exec(conf->match_line, conf->match_line_extra, b->ptr, b->used - 1, 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, b->ptr); } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); } return -1; } if (n >= 18) { #ifdef DEBUG_PCRE int i; #endif char *c; pcre_get_substring_list(b->ptr, ovector, n, &list); /* 1 - date 2 - calling number 3 - called number 4 - seconds 5 - mseconds / 10 6 - timestamp 7 - units 8 - direction (I O) 9 - ?? 10 - bytes in 11 - bytes out 12 - version tag (3.1, 3.2) 13 - service type 14 - ?? 15 - cost per unit 16 - currency 17 - cost 18 - ?? or 18 - (murks) 19 - provider 20 - ?? */ parse_timestamp(ext_conf, list[1], record); #ifdef DEBUG_PCRE for (i = 0; i < n; i++) { printf("%d: %s\n",i, list[i]); } #endif c = (char *)list[8]; switch(*c) { case 'O': rectel->direction = M_RECORD_TELECOM_DIRECTION_OUT; break; case 'I': rectel->direction = M_RECORD_TELECOM_DIRECTION_IN; break; default: fprintf(stderr, "%s.%d: unknown diretion type: %c\n", __FILE__, __LINE__, *c); return -1; } rectel->calling_number = malloc(strlen((char *)list[2])+1); strcpy(rectel->calling_number, (char *)list[2]); rectel->called_number = malloc(strlen((char *)list[3])+1); strcpy(rectel->called_number, list[3]); rectel->duration = strtol(list[4], NULL, 10)-1; if (rectel->ext) { recint = rectel->ext; } else { recint = mrecord_init_telecom_internal(); } recint->units_to_pay = strtol(list[7], NULL, 10)-1; rectel->ext = recint; rectel->ext_type = M_RECORD_TYPE_TELECOM_INTERNAL; free(list); } else { fprintf(stderr, "%s.%d: Matched fields below minimum: %d\n", __FILE__, __LINE__, n); return -1; } return 0; #undef N } int mplugins_input_isdnlog_get_next_record(mconfig *ext_conf, mlogrec *record) { int ret = 0; config_input *conf = ext_conf->plugin_conf; if (record == NULL) return M_RECORD_HARD_ERROR; /* fill the line buffer */ if (NULL == mgets(&(conf->inputfile), conf->buf)) return M_RECORD_EOF; ret = parse_record_pcre (ext_conf, record, conf->buf); if (ret == M_RECORD_CORRUPT) { M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_WARNINGS, "affected Record: %s\n", conf->buf->ptr ); } return ret; }