/*
- (C) 2007-2017 Proxmox Server Solutions GmbH, All Rights Reserved
+ (C) 2007-2017 Proxmox Server Solutions GmbH, All Rights Reserved
- Proxmox Mail Tracker
+ Proxmox Mail Tracker
- See http://www.proxmox.com for more information
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ Author: Dietmar Maurer <dietmar@proxmox.com>
+
+ See http://www.proxmox.com for more information
*/
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
+#include <stdint.h>
#include <zlib.h>
#include <fnmatch.h>
//#define EPOOL_MAX_SIZE 128
#define EPOOL_BLOCK_SIZE 2048
#define EPOOL_MAX_SIZE 128
-#define MAX_LOGFILES 31
+#define MAX_LOGFILES 32
//#define EPOOL_DEBUG
//#define DEBUG
TOList *next;
};
+#define MatchTypeQID 1
+#define MatchTypeRelLineNr 2
+
+typedef struct _MatchList MatchList;
+struct _MatchList {
+ unsigned int mtype;
+ char *id;
+ time_t ltime;
+ unsigned long rel_line_nr;
+ MatchList *next;
+};
+
#ifdef DEBUG
GHashTable *smtpd_debug_alloc;
GHashTable *qmgr_debug_alloc;
time_t start;
time_t end;
time_t ctime;
+ MatchList *match_list;
char *server;
char *msgid;
- char *qid;
char *strmatch;
unsigned long limit;
unsigned long count;
struct _LogEntry {
const char *text;
+ unsigned long linenr;
LogEntry *next;
};
char *connect;
+ // time,rel_line_nr is used as cursor/ID
+ time_t ltime;
+ unsigned long rel_line_nr;
+
//unsigned int external:1; // not from local host
unsigned int disconnect:1;
unsigned int strmatch:1;
// Prototypes
void debug_error (char *msg, const char *line);
-SList *slist_remove (SList *list, gpointer data);
EPool *epool_init (EPool *ep);
void epool_free (EPool *ep);
char *epool_strdup (EPool *ep, const char *s);
void loglist_print (LogList *loglist);
-void loglist_add (EPool *ep, LogList *loglist, const char *text, int len);
+void loglist_add (EPool *ep, LogList *loglist, const char *text, int len, unsigned long linenr);
-SEntry *sentry_new (int pid);
-SEntry *sentry_get (LParser *parser, int pid);
+SEntry *sentry_new (int pid, time_t ltime, unsigned long rel_line_nr);
+SEntry *sentry_get (LParser *parser, int pid, time_t ltime, unsigned long rel_line_nr);
void sentry_ref_add (SEntry *sentry, QEntry *qentry);
int sentry_ref_del (SEntry *sentry, QEntry *qentry);
void sentry_ref_finalize (LParser *parser, SEntry *sentry);
// Implementations
+// Checksum Macros
+#define PROXPROX 0xE0E4DEF0
+#define PMG_SMTP_FILTER 0x0A85A6B7
+#define POSTFIX_POSTSCREEN 0xD17E2019
+#define POSTFIX_QMGR 0x48465316
+#define POSTFIX_SMTP 0x4A466014
+#define POSTFIX_LMTP 0x43466014
+#define POSTFIX_LOCAL 0x484F05AF
+#define POSTFIX_ERROR 0x4B5E13AE
+#define POSTFIX_SMTPD 0x466014AE
+#define POSTFIX_CLEANUP 0x05A8BAC1
+
//#define LOGPATH "./log/"
#define LOGPATH "/var/log/"
-//#define LOGPATH "/var/log5/"
+//#define LOGPATH "/root/testlog/"
static const char *logfiles[] = {
LOGPATH "syslog",
#endif
}
-SList *
-slist_remove (SList *list, gpointer data)
-{
- SList *p = NULL;
- SList *l = list;
-
- while (l) {
- if (l->data == data) {
- if (p)
- p->next = l->next;
- if (list == l)
- list = list->next;
-
- l->next = NULL;
-
- break;
- }
-
- p = l;
- l = l->next;
- }
-
- return list;
-}
-
EPool *
epool_init (EPool *ep)
{
if (size > EPOOL_MAX_SIZE) {
SList *blocks;
if (space >= sizeof (SList)) {
- blocks = ep->blocks->data + ep->cpos;
+ blocks = (SList *)((char *)ep->blocks->data + ep->cpos);
ep->cpos += sizeof (SList);
} else {
blocks = (SList *)epool_alloc (ep, sizeof (SList));
return data;
} else if (space >= rs) {
- data = ep->blocks->data + ep->cpos;
+ data = (char *)ep->blocks->data + ep->cpos;
ep->cpos += rs;
return data;
} else {
- SList *blocks = ep->blocks->data + ep->cpos;
+ SList *blocks = (SList *)((char *)ep->blocks->data + ep->cpos);
data = g_slice_alloc0 (EPOOL_BLOCK_SIZE);
blocks->data = data;
{
LogEntry *log = loglist->log;
while (log) {
- printf ("%s", log->text);
+ printf ("L%08lX %s", log->linenr, log->text);
log = log->next;
}
}
void
-loglist_add (EPool *ep, LogList *loglist, const char *text, int len)
+loglist_add (EPool *ep, LogList *loglist, const char *text, int len, unsigned long linenr)
{
LogEntry *log;
log = epool_alloc (ep, sizeof (LogEntry));
log->text = epool_strndup (ep, text, len);
+ log->linenr = linenr;
log->next = NULL;
if (loglist->logs_last) {
}
SEntry*
-sentry_new (int pid)
+sentry_new (int pid, time_t ltime, unsigned long rel_line_nr)
{
SEntry *sentry;
SList *blocks;
sentry = (SEntry *)g_slice_alloc0(EPOOL_BLOCK_SIZE);
sentry->pid = pid;
+ sentry->ltime = ltime;
+ sentry->rel_line_nr = rel_line_nr;
#ifdef EPOOL_DEBUG
sentry->ep.allocated += EPOOL_BLOCK_SIZE;
}
SEntry *
-sentry_get (LParser *parser, int pid)
+sentry_get (LParser *parser, int pid, time_t ltime, unsigned long rel_line_nr)
{
SEntry *sentry;
return sentry;
} else {
- if ((sentry = sentry_new (pid))) {
+ if ((sentry = sentry_new (pid, ltime, rel_line_nr))) {
g_hash_table_insert (parser->smtpd_h, &sentry->pid, sentry);
}
{
NQList *nq;
- if (parser->msgid || parser->qid) return;
+ if (parser->msgid) return;
if (parser->server) {
if (!sentry->connect) return;
if (!strcasestr (sentry->connect, parser->server)) return;
}
+ MatchList *match = parser->match_list;
+ if (match) {
+ int found = 0;
+ while(match) {
+ if (match->mtype == MatchTypeQID) {
+ return;
+ } else if (match->mtype == MatchTypeRelLineNr) {
+ if (match->ltime == sentry->ltime && match->rel_line_nr == sentry->rel_line_nr) {
+ found = 1;
+ break;
+ }
+ } else {
+ g_error("implement me");
+ }
+ match = match->next;
+ }
+ if (!found) return;
+ }
+
if (parser->from || parser->to ||
parser->exclude_greylist || parser->exclude_ndrs) {
nq = sentry->nqlist;
if (parser->verbose) {
- printf ("SMTPD:\n");
+ printf ("SMTPD: T%08lXL%08lX\n", sentry->ltime, sentry->rel_line_nr);
printf ("CTIME: %08lX\n", parser->ctime);
- if (sentry->connect) { printf ("CONNECT: %s\n", sentry->connect); }
+ if (sentry->connect) { printf ("CLIENT: %s\n", sentry->connect); }
//printf ("EXTERNAL: %d\n", sentry->external);
}
nq = sentry->nqlist;
while (nq) {
if (nq->from && nq->to && nq->dstatus) {
- printf ("TO:%08lX:00000000000:%c: from <%s> to <%s>\n", nq->ltime, nq->dstatus, nq->from, nq->to);
+ printf ("TO:%08lX:T%08lXL%08lX:%c: from <%s> to <%s>\n", nq->ltime,
+ sentry->ltime, sentry->rel_line_nr, nq->dstatus,
+ nq->from, nq->to);
parser->count++;
}
nq = nq->next;
}
- if (parser->verbose) {
+ if (!parser->verbose) { fflush (stdout); return; }
+
+ if (parser->verbose > 1) {
printf ("LOGS:\n");
loglist_print (&sentry->loglist);
- printf ("\n");
}
+ printf ("\n");
+
fflush (stdout);
}
if (strcasecmp (parser->msgid, qentry->msgid)) return;
}
- if (parser->qid) {
+ MatchList *match = parser->match_list;
+ if (match) {
int found = 0;
- if (fe && !strcmp (fe->logid, parser->qid)) found = 1;
- if (!strcmp (qentry->qid, parser->qid)) found = 1;
-
- if (!found) return;
+ while(match) {
+ if (match->mtype == MatchTypeQID) {
+ if ((fe && !strcmp (fe->logid, match->id)) ||
+ (!strcmp (qentry->qid, match->id))) {
+ found = 1;
+ break;
+ }
+ } else if (match->mtype == MatchTypeRelLineNr) {
+ if (se && match->ltime == se->ltime && match->rel_line_nr == se->rel_line_nr) {
+ found = 1;
+ break;
+ }
+ } else {
+ g_error("implement me");
+ }
+ match = match->next;
+ }
+ if (!found) return;
}
if (parser->server) {
printf ("CTIME: %08lX\n", parser->ctime);
printf ("SIZE: %u\n", qentry->size);
- if (qentry->client) { printf ("CLIENT: %s\n", qentry->client); }
+ if (qentry->client) {
+ printf ("CLIENT: %s\n", qentry->client);
+ } else if (se && se->connect) {
+ printf ("CLIENT: %s\n", se->connect);
+ }
if (qentry->msgid) { printf ("MSGID: %s\n", qentry->msgid); }
if (!parser->verbose) { fflush (stdout); return; }
- if (se) {
+ if (parser->verbose > 1) {
- if (se->loglist.log) {
+ if (se && se->loglist.log) {
printf ("SMTP:\n");
loglist_print (&se->loglist);
}
- }
- if (fe) {
- if (fe->loglist.log) {
- printf ("FILTER: %s\n", fe->logid);
- loglist_print (&fe->loglist);
- }
- }
+ if (fe && fe->loglist.log) {
+ printf ("FILTER: %s\n", fe->logid);
+ loglist_print (&fe->loglist);
+ }
- if (qentry->loglist.log) {
- printf ("QMGR:\n");
- loglist_print (&qentry->loglist);
+ if (qentry->loglist.log) {
+ printf ("QMGR:\n");
+ loglist_print (&qentry->loglist);
+ }
}
printf ("\n");
return res;
}
+#define JAN (('J'<<16)|('a'<<8)|'n')
+#define FEB (('F'<<16)|('e'<<8)|'b')
+#define MAR (('M'<<16)|('a'<<8)|'r')
+#define APR (('A'<<16)|('p'<<8)|'r')
+#define MAY (('M'<<16)|('a'<<8)|'y')
+#define JUN (('J'<<16)|('u'<<8)|'n')
+#define JUL (('J'<<16)|('u'<<8)|'l')
+#define AUG (('A'<<16)|('u'<<8)|'g')
+#define SEP (('S'<<16)|('e'<<8)|'p')
+#define OCT (('O'<<16)|('c'<<8)|'t')
+#define NOV (('N'<<16)|('o'<<8)|'v')
+#define DEC (('D'<<16)|('e'<<8)|'c')
+
time_t
parse_time (const char **text, int len)
{
// parse month
int csum = (line[0]<<16) + (line[1]<<8) + line[2];
-
+
switch (csum) {
- case 4874606: mon = 0; break;
- case 4613474: mon = 1; break;
- case 5071218: mon = 2; break;
- case 4288626: mon = 3; break;
- case 5071225: mon = 4; break;
- case 4879726: mon = 5; break;
- case 4879724: mon = 6; break;
- case 4289895: mon = 7; break;
- case 5465456: mon = 8; break;
- case 5202804: mon = 9; break;
- case 5140342: mon = 10; break;
- case 4482403: mon = 11; break;
- default:
+ case JAN: mon = 0; break;
+ case FEB: mon = 1; break;
+ case MAR: mon = 2; break;
+ case APR: mon = 3; break;
+ case MAY: mon = 4; break;
+ case JUN: mon = 5; break;
+ case JUL: mon = 6; break;
+ case AUG: mon = 7; break;
+ case SEP: mon = 8; break;
+ case OCT: mon = 9; break;
+ case NOV: mon = 10; break;
+ case DEC: mon = 11; break;
+ default:
debug_error ("unable to parse month", line);
return 0;
}
return 0;
}
- found = 0; while (isdigit (*cpos)) { mday = mday*10 + *cpos - 48; cpos++; found++; }
+ found = 0; while (isdigit (*cpos)) { mday = mday*10 + *cpos - '0'; cpos++; found++; }
if (found < 1 || found > 2) {
debug_error ("unable to parse day of month", line);
return 0;
return 0;
}
- found = 0; while (isdigit (*cpos)) { hour = hour*10 + *cpos - 48; cpos++; found++; }
+ found = 0; while (isdigit (*cpos)) { hour = hour*10 + *cpos - '0'; cpos++; found++; }
if (found < 1 || found > 2) {
debug_error ("unable to parse hour", line);
return 0;
}
cpos++;
- found = 0; while (isdigit (*cpos)) { min = min*10 + *cpos - 48; cpos++; found++; }
+ found = 0; while (isdigit (*cpos)) { min = min*10 + *cpos - '0'; cpos++; found++; }
if (found < 1 || found > 2) {
debug_error ("unable to parse minute", line);
return 0;
}
cpos++;
- found = 0; while (isdigit (*cpos)) { sec = sec*10 + *cpos - 48; cpos++; found++; }
+ found = 0; while (isdigit (*cpos)) { sec = sec*10 + *cpos - '0'; cpos++; found++; }
if (found < 1 || found > 2) {
debug_error ("unable to parse second", line);
return 0;
const char *line;
gzFile stream;
- for (i = 0; i < MAX_LOGFILES; i++) {
+ for (i = 0; i < (MAX_LOGFILES - 1); i++) {
cur_year = parser->year[i];
cur_month = 0;
fprintf (stderr, "\t-e END end time (YYYY-MM-DD HH:MM:SS)\n");
fprintf (stderr, "\t or seconds since epoch\n");
fprintf (stderr, "\t-m MSGID message ID (exact match)\n");
- fprintf (stderr, "\t-q QID queue ID (exact match)\n");
+ fprintf (stderr, "\t-q QID queue ID (exact match), can be\n");
+ fprintf (stderr, "\t specified multiple times.\n");
fprintf (stderr, "\t-x STRING search for strings\n");
fprintf (stderr, "\t-l LIMIT print max limit entries\n");
- fprintf (stderr, "\t-v verbose output\n");
+ fprintf (stderr, "\t-g exclude greylist entries\n");
+ fprintf (stderr, "\t-n exclude NDR entries\n");
+ fprintf (stderr, "\t-v verbose output (no logs)\n");
+ fprintf (stderr, "\t-vv verbose output with logs\n");
}
// gzgets is ways too slow, so we do it our own way
-static int
+static char
mygzgetc (gzFile stream)
{
int br;
static char *
mygzgets (gzFile stream, char *line, int bufsize)
{
- int c=0;
+ char c=0;
char *cpos;
cpos = line;
{
char linebuf[linebufsize];
char *line;
- char *uniqueid = NULL;
+ char *inputfile = NULL;
const char *text;
const char *idx1;
const char *idx2;
const char *cpos;
int found = 0;
- int csum_prog;
- int lines = 0;
+ uint32_t csum_prog;
+ unsigned long lines = 0;
+ unsigned long rel_line_nr = 0;
char qidbuf[30];
int i;
struct tm *ltime;
struct timeval tv;
- time_t ctime, start, end;
+ time_t ctime, next_ctime, start, end;
LParser *parser;
int opt;
exit (-1);
}
- while ((opt = getopt (argc, argv, "f:t:s:e:h:m:q:x:l:I:vgn")) != -1) {
+ while ((opt = getopt (argc, argv, "f:t:s:e:h:m:q:x:i:l:vgn")) != -1) {
if (opt == 'f') {
parser->from = epool_strdup (&parser->ep, optarg);
} else if (opt == 't') {
parser->to = epool_strdup (&parser->ep, optarg);
} else if (opt == 'v') {
- parser->verbose = 1;
+ parser->verbose += 1;
} else if (opt == 'g') {
parser->exclude_greylist = 1;
} else if (opt == 'n') {
parser->exclude_ndrs = 1;
- } else if (opt == 'I') {
- uniqueid = optarg;
} else if (opt == 'h') {
parser->server = epool_strdup (&parser->ep, optarg);
} else if (opt == 'm') {
parser->msgid = epool_strdup (&parser->ep, optarg);
} else if (opt == 'q') {
- parser->qid = epool_strdup (&parser->ep, optarg);
+ time_t ltime;
+ unsigned long rel_line_nr;
+ MatchList *match = (MatchList *)epool_alloc(&parser->ep, sizeof(MatchList));
+ if (sscanf(optarg, "T%08lXL%08lX", <ime, &rel_line_nr) == 2) {
+ match->mtype = MatchTypeRelLineNr;
+ match->ltime = ltime;
+ match->rel_line_nr = rel_line_nr;
+ match->next = parser->match_list;
+ parser->match_list = match;
+ } else {
+ match->mtype = MatchTypeQID;
+ match->id = epool_strdup(&parser->ep, optarg);
+ match->next = parser->match_list;
+ parser->match_list = match;
+ }
} else if (opt == 'x') {
parser->strmatch = epool_strdup (&parser->ep, optarg);
+ } else if (opt == 'i') {
+ inputfile = optarg;
} else if (opt == 'l') {
char *l;
parser->limit = strtoul (optarg, &l, 0);
}
int filecount;
- if ((filecount = parser_count_files (parser)) <= 0) {
+ if (inputfile) {
+ filecount = 1;
+ } else if ((filecount = parser_count_files (parser)) <= 0) {
fprintf (stderr, "unable to access log files\n");
exit (-1);
}
- if (uniqueid) {
- printf ("# LogReader: %d %s\n", getpid(), uniqueid);
- } else {
- printf ("# LogReader: %d\n", getpid());
- }
+ printf ("# LogReader: %d\n", getpid());
printf ("# Query options\n");
if (parser->from) printf ("# Sender: %s\n", parser->from);
if (parser->to) printf ("# Recipient: %s\n", parser->to);
if (parser->server) printf ("# Server: %s\n", parser->server);
if (parser->msgid) printf ("# MsgID: %s\n", parser->msgid);
- if (parser->qid) printf ("# QID: %s\n", parser->qid);
+
+ MatchList *match = parser->match_list;
+ while (match) {
+ if (match->mtype == MatchTypeQID) {
+ printf ("# QID: %s\n", match->id);
+ } else if (match->mtype == MatchTypeRelLineNr) {
+ printf ("# QID: T%08lXL%08lX\n", match->ltime, match->rel_line_nr);
+ } else {
+ g_error("internal error - unknown match type %d\n", match->mtype);
+ }
+ match = match->next;
+ }
+
if (parser->strmatch) printf ("# Match: %s\n", parser->strmatch);
strftime (linebuf, 256, "%F %T", gmtime (&parser->start));
cur_year = parser->year[i];
if (i <= 1) {
- if (!(stream = (gpointer) fopen (logfiles[i], "r"))) continue;
+ if (inputfile && strlen(inputfile) == 1 && *inputfile == '-') {
+ stream = (gpointer) stdin;
+ } else if (inputfile) {
+ if (!(stream = (gpointer) fopen (inputfile, "r"))) {
+ fprintf(stderr, "unable to open log file\n");
+ exit (-1);
+ }
+ } else if (!(stream = (gpointer) fopen (logfiles[i], "r"))) continue;
} else {
if (!(stream = (gpointer) gzopen (logfiles[i], "r"))) continue;
}
int pid = 0;
cpos = line;
- if (!(ctime = parse_time (&cpos, len))) {
+
+ next_ctime = parse_time (&cpos, len);
+
+ if (!next_ctime) {
continue;
- }
+ }
+
+ if (next_ctime != ctime) {
+ rel_line_nr = 0;
+ } else {
+ rel_line_nr++;
+ }
+
+ ctime = next_ctime;
if (ctime < start) continue;
if (ctime > end) break;
}
//printf ("LINE: %s\n", line);
- //const char prog = cpos;
+ //const char *prog = cpos;
csum_prog = 0;
found = 0; while (*cpos && (*cpos != ':') && (*cpos != '[')) {
- csum_prog = (csum_prog <<8) + *cpos;
+ csum_prog = ((csum_prog << 8)|(csum_prog >> 24)) + *cpos;
cpos++;
found++;
}
//idx1 = g_strndup (prog, found);
//printf ("TEST:%s:%08X\n", idx1, csum_prog);
- //g_free (idx1);
+ //free (idx1);
if (*cpos == '[') {
cpos++;
found = 0; while (isdigit (*cpos)) {
- pid = pid*10 + *cpos - 48;
+ pid = pid*10 + *cpos - '0';
cpos++;
found++;
}
strmatch = 1;
}
- if (csum_prog == 0x70726F78) { // proxprox
+ if ((csum_prog == PROXPROX) ||
+ (csum_prog == PMG_SMTP_FILTER)) {
if ((idx1 = parse_qid (&cpos, qidbuf, ':', 25))) {
continue;
}
- loglist_add (&fe->ep, &fe->loglist, line, len);
+ loglist_add (&fe->ep, &fe->loglist, line, len, lines);
if (strmatch) fe->strmatch = 1;
}
- } else if (csum_prog == 0x7265656E) { // postfix/postscreen
+ } else if (csum_prog == POSTFIX_POSTSCREEN) {
SEntry *se;
if (*cpos != '>') continue;
- if (!(se = sentry_get (parser, pid))) {
+ if (!(se = sentry_get (parser, pid, ctime, rel_line_nr))) {
continue;
}
if (strmatch) se->strmatch = 1;
- loglist_add (&se->ep, &se->loglist, line, len);
+ loglist_add (&se->ep, &se->loglist, line, len, lines);
sentry_nqlist_add (se, ctime, from, idx1 - from, to, cpos - to, 'N');
sentry_free (parser, se);
}
- } else if (csum_prog == 0x716D6772) { // postfix/qmgr
+ } else if (csum_prog == POSTFIX_QMGR) {
if ((idx2 = text) && (idx1 = parse_qid (&idx2, qidbuf, ':', 15))) {
qe->cleanup = 1;
- loglist_add (&qe->ep, &qe->loglist, line, len);
+ loglist_add (&qe->ep, &qe->loglist, line, len, lines);
if ((*idx2 == 'f') && !strncmp (idx2, "from=<", 6)) {
int size = 0;
cpos += 7;
- while (isdigit (*cpos)) { size = size*10 + *cpos++ - 48; }
+ while (isdigit (*cpos)) { size = size*10 + *cpos++ - '0'; }
qe->size = size;
}
}
}
- } else if ((csum_prog == 0x736D7470) || //postfix/smtp
- (csum_prog == 0x6C6D7470)) { //postfix/lmtp
+ } else if ((csum_prog == POSTFIX_SMTP) ||
+ (csum_prog == POSTFIX_LMTP) ||
+ (csum_prog == POSTFIX_LOCAL) ||
+ (csum_prog == POSTFIX_ERROR)) {
- int lmtp = (csum_prog == 0x6C6D7470);
+ int lmtp = (csum_prog == POSTFIX_LMTP);
if ((cpos = text) && (idx1 = parse_qid (&cpos, qidbuf, ':', 15))) {
qe->cleanup = 1;
- loglist_add (&qe->ep, &qe->loglist, line, len);
+ loglist_add (&qe->ep, &qe->loglist, line, len, lines);
if (strncmp (cpos, "to=<", 4)) continue;
cpos += 4;
}
}
- } else if (csum_prog == 0x6D747064) { // postfix/smtpd
+ } else if (csum_prog == POSTFIX_SMTPD) {
SEntry *se;
if (!pid) {
continue;
}
- if (!(se = sentry_get (parser, pid))) {
+ if (!(se = sentry_get (parser, pid, ctime, rel_line_nr))) {
continue;
}
if (strmatch) se->strmatch = 1;
- loglist_add (&se->ep, &se->loglist, line, len);
+ loglist_add (&se->ep, &se->loglist, line, len, lines);
if ((*text == 'c') && !strncmp (text, "connect from ", 13)) {
}
- } else if (csum_prog == 0x616E7570) { // postfix/cleanup
+ } else if (csum_prog == POSTFIX_CLEANUP) {
QEntry *qe;
if (strmatch) qe->strmatch = 1;
- loglist_add (&qe->ep, &qe->loglist, line, len);
+ loglist_add (&qe->ep, &qe->loglist, line, len, lines);
if ((*idx2 == 'm') && !strncmp (idx2, "message-id=", 11)) {